[ServiceContract]
public interface IComplexService
{
[OperationContract]
int Sum(int x, int y);
}
public class ComplexService : IComplexService
{
public int Sum(int x, int y)
{
return x + y;
}
}class Program
{
static void Main(string[] args)
{
Console.WriteLine(
Core.ComplexService.Sum(2, 5)
);
Console.ReadLine();
}
}public static class Core
{
public static IComplexService ComplexService
{
get
{
if (ConfigurationManager.AppSettings["userService"] == "1")
return new ComplexService();
return new ChannelFactory<IComplexService>("BasicHttpBinding_ComplexService")
.CreateChannel();
}
}
}
Bu durumda kendi proxy nesnelerimiz üretebileceğimiz bir yapıya ihtiyaçımız var. Bunun için bir çok çözüm var; biz burada RealProxy nesnesini kullanıyor olacağız. (Konu hakkında ayrıntılı bilgi için Sefer Algan Hocam'ın yazdığı CSharpNedir'deki şu makalesine göz atabilirsiniz).
internal class ProxyFactory<TObject> : RealProxy
{
public TObject RealObject { get; private set; }
public ProxyFactory(TObject realObject)
: base(typeof(TObject))
{
this.RealObject = realObject;
}
private Func<Func<object>, object> _surroundDelegate;
public TObject GetProxy(Func<Func<object>, object> surroundDelegate)
{
this._surroundDelegate = surroundDelegate;
return (TObject)this.GetTransparentProxy();
}
public override IMessage Invoke(IMessage msg)
{
//Bu örnek gelen çağrımın bir metot olduğu varsayımı altında yapılmıştır.
//Eğer çağrım bir Property ise ona göre bu kodu değiştirmek gerekir.Yani set_ ve get_ önekleri ile metodu dinamik bir şekilde çağırmak gerekir.
IMethodCallMessage message = (IMethodCallMessage)msg;
if (message != null)
{
//MessageBox.Show(message.MethodName + " metodu çağrılmak üzere. Biz araya girdik çağrılmadan önce");
object methodRetval = _surroundDelegate(() => message.MethodBase.Invoke(RealObject, message.InArgs));
ReturnMessage retVal = new ReturnMessage(methodRetval, null, 0, message.LogicalCallContext, message);
return retVal;
}
return null;
}
}
- 5 numaralı satır'da; bir nesnenin proxy'ini üretmek için ProxyGenerator sınıfını üretirken; gerçek nesneyi de vermeyi zorunlu tutuyoruz.
- 13 numaralı satırda method parametresi :"Func<Func<object>, object>". Yani içerisine object tipinde değer döndüren; verilen Delegate'i çalıştırıp, dönen değeri geri bize veren bir Delegate istenmektedir. Biliyorum cümle çok karmaşık oldu ama kod yeterince açık değil mi zaten :D
- 30 numaralı satırda ise; proxy nesne üzerinden çağrılan, gerçek sınıfın methodlarını çağırdığında GetProxy nesnesinde aldığımız delegate; içerisine gerçek nesnenin ilgili methodunu barındıran delegate verilerek çalıştırılıyor.
public static class Core
{
public static IComplexService ComplexService
{
get
{
if (ConfigurationManager.AppSettings["useService"] == "0")
return new ComplexService();
//return new ChannelFactory<IComplexService>("BasicHttpBinding_ComplexService").CreateChannel();
var proxyCreater = new ProxyFactory<IComplexService>(
new ChannelFactory<IComplexService>("BasicHttpBinding_ComplexService")
.CreateChannel()
);
return proxyCreater.GetProxy(fnc =>
{
using (OperationContextScope scope = new OperationContextScope(proxyCreater.RealObject as IContextChannel))
{
return fnc.Invoke();
}
});
}
}
}Artık istediğimiz an basit bir konfigurasyon ayarıyla sistemimizi WCF üzerinden çalışır hale getirebiliriz. Üstelik servis method'larını çalıştırıken tekrar etmek zorunda kaldığımız kodları da merkezi noktalara çekebilmiş olduk.
Çalışan örneğin kaynak kodlarını buradan indirebilirsiniz.
Umarım fikrimi yeterince "Cin" bulumuşsunuzdur :)
Sıradışı günler, sıradışı başarılar dilerim.