This is how I used to make method calls:
SvcHelper.Using<SomeWebServiceClient>(proxy =>
{
proxy.SomeMethod();
}
public class SvcHelper
{
public static void Using<TClient>(Action<TClient> action) where TClient : ICommunicationObject, IDisposable, new()
{
}
}
This is how I make method calls:
ChannelFactory<ISomethingWebService> cnFactory = new ChannelFactory<ISomethingWebService>("SomethingWebService");
ISomethingWebService client = cnFactory.CreateChannel();
using (new OperationContextScope((IContextChannel)client))
{
client.SomeMethod();
}
My question is: Instead of replacing every instance of my original method call approach; Is there a way to modify my SvcHelper and do the creation of the channel in the SvcHelper constructor and then simply pass the interface like the following:
SvcHelper.Using<ISomethingWebService>(client =>
{
client.SomeMethod();
}
Hope this makes sense and thanks in advance.
First, you don't want to create a new ChannelFactory<T> every call to the Using helper method. They are the most costly thing to construct in the WCF universe. So, at bare minimum, you will want to use a caching approach there.
Second, you don't want to tie yourself to "client" types at all anymore. Just work straight with the service contract interfaces.
Starting from what you've got, here's where I'd go based on how I've done this in the past:
public class SvcHelper
{
private static ConcurrentDictionary<ChannelFactoryCacheKey, ChannelFactory> ChannelFactories = new ConcurrentDictionary<ChannelFactoryCacheKey, ChannelFactory>();
public static void Using<TServiceContract>(Action<TServiceContract> action) where TServiceContract : class
{
SvcHelper.Using<TServiceContract>(action, "*");
}
public static void Using<TServiceContract>(Action<TServiceContract> action, string endpointConfigurationName) where TServiceContract : class
{
ChannelFactoryCacheKey cacheKey = new ChannelFactoryCacheKey(typeof(TServiceContract), endpointConfigurationName);
ChannelFactory<TServiceContract> channelFactory = (ChannelFactory<TServiceContract>)SvcHelper.ChannelFactories.GetOrAdd(
cacheKey,
missingCacheKey => new ChannelFactory<TServiceContract>(missingCacheKey.EndpointConfigurationName));
TServiceContract typedChannel = channelFactory.CreateChannel();
IClientChannel clientChannel = (IClientChannel)typedChannel;
try
{
using(new OperationContextScope((IContextChannel)typedChannel))
{
action(typedChannel);
}
}
finally
{
try
{
clientChannel.Close();
}
catch
{
clientChannel.Abort();
}
}
}
private sealed class ChannelFactoryCacheKey : IEquatable<ChannelFactoryCacheKey>
{
public ChannelFactoryCacheKey(Type channelType, string endpointConfigurationName)
{
this.channelType = channelType;
this.endpointConfigurationName = endpointConfigurationName;
}
private Type channelType;
public Type ChannelType
{
get
{
return this.channelType;
}
}
private string endpointConfigurationName;
public string EndpointConfigurationName
{
get
{
return this.endpointConfigurationName;
}
}
public bool Equals(ChannelFactoryCacheKey compareTo)
{
return object.ReferenceEquals(this, compareTo)
||
(compareTo != null
&&
this.channelType == compareTo.channelType
&&
this.endpointConfigurationName == compareTo.endpointConfigurationName);
}
public override bool Equals(object compareTo)
{
return this.Equals(compareTo as ChannelFactoryCacheKey);
}
public override int GetHashCode()
{
return this.channelType.GetHashCode() ^ this.endpointConfigurationName.GetHashCode();
}
}
}
This should work:
public class SvcHelper
{
public static void Using<TClient>(Action<TClient> action) where TClient : ICommunicationObject, IDisposable
{
ChannelFactory<TClient> cnFactory = new ChannelFactory<TClient>("SomethingWebService");
TClient client = cnFactory.CreateChannel();
using (new OperationContextScope((IContextChannel)client))
{
action(client);
}
}
}
Related
I have an interface as below, which I use to add a specific language if it does not exist:
public interface IGetLanguagesService
{
void GetLanguages(ILocalizationService localization);
}
public class LanguageService : IGetLanguagesService
{
ILocalizationService _localizationService;
public void GetLanguages(ILocalizationService localization)
{
_localizationService = localization;
var currentLanguages = _localizationService.GetAllLanguages();
bool exists = false;
foreach (var currentLan in currentLanguages)
{
if (currentLan.IsoCode == "es-ES")
{
exists = true;
}
}
if (!exists)
{
AddLanguage(_localizationService);
}
}
public void AddLanguage(ILocalizationService localization)
{
var languageSE = new Language("es-ES") { CultureName = "es-ES", IsMandatory = true };
localization.Save(languageSE);
}
}
I want to use this at start-up so have created a component composer, which on Initialize() I want to call CallGetLanguages() but Im not entirely sure what should be in Initialize(), I think my DI may be wrong?
public class LanguagesComposer : ComponentComposer<LanguagesComponent>
{
public void Compose(Composition composition)
{
composition.Register<IGetLanguagesService>(Lifetime.Singleton);
composition.Register<ILocalizationService>(Lifetime.Singleton);
composition.Components().Append<LanguagesComponent>();
}
}
public class LanguagesComponent : IComponent
{
public void Initialize()
{
???????
}
public void Terminate()
{
throw new NotImplementedException();
}
IGetLanguagesService _getLanguagesService;
ILocalizationService _localization;
public void CallGetLanguages(IGetLanguagesService getLanguages, ILocalizationService localization)
{
_getLanguagesService = getLanguages;
_localization = localization;
_getLanguagesService.GetLanguages(localization);
}
}
You've passed ILocalizationService localization instance to LanguageService twice, pass it to constructor instead and use a constructor injection. The same issue with LanguagesComponent, pass all its dependencies to constructor instead of methods
While troubleshooting a wcf client issue I came across some code from #marc-gravell here. I read the article a number of times and then decided to try and see if I could use the code for real so I created a console app and pulled it all in.
Wrapper:
public interface IDisposableWrapper<T> : IDisposable
{
T BaseObject { get; }
}
public class DisposableWrapper<T> : IDisposableWrapper<T> where T : class, IDisposable
{
public T BaseObject { get; private set; }
public DisposableWrapper(T baseObject) { BaseObject = baseObject; }
protected virtual void OnDispose()
{
BaseObject.Dispose();
}
public void Dispose()
{
if (BaseObject != null)
{
try
{
OnDispose();
}
catch
{
// swallow...
}
}
BaseObject = null;
}
}
Extensions:
public static class DisposableExtensions
{
// core "just dispose it without barfing"
public static IDisposableWrapper<T> Wrap<T>(this T baseObject)
where T : class, IDisposable
{
if (baseObject is IDisposableWrapper<T>) return (IDisposableWrapper<T>)baseObject;
return new DisposableWrapper<T>(baseObject);
}
// specific handling for service-model
public static IDisposableWrapper<TProxy> Wrap<TProxy, TChannel>(this TProxy proxy)
where TProxy : ClientBase<TChannel>
where TChannel : class
{
return new ClientWrapper<TProxy, TChannel>(proxy);
}
}
ClientWrapper:
public class ClientWrapper<TProxy, TChannel> : DisposableWrapper<TProxy>
where TProxy : ClientBase<TChannel>
where TChannel : class
{
public ClientWrapper(TProxy proxy) : base(proxy)
{
}
protected override void OnDispose()
{
// lots of code per state of BaseObject
//State != CommunicationState.Faulted;
}
}
Now, when I go to use it, I have this:
static void Main(string[] args)
{
using (var proxy = new PLPlacementServiceClient())
{
var result = proxy.GetDocumentClassForNewBusiness();
}
using (var proxy = new PLPlacementServiceClient().Wrap())
{
var result = proxy.BaseObject.GetDocumentClassForNewBusiness();
}
using (var proxy = new PLPlacementServiceClient().Wrap<>())//what goes here?
{
var result = proxy.BaseObject.GetDocumentClassForNewBusiness();
}
}
When I F-12 the PLPlacementServiceClient().Wrap() method , it takes me to the non-generic implementation in the extensions class
IDisposableWrapper<T> Wrap<T>(this T baseObject)
, but I was expecting to be taken to the other signature
IDisposableWrapper<TProxy> Wrap<TProxy, TChannel>(this TProxy proxy)
So here is my question(s), "How do I invoke the ClientBase version of the extension?"
Thank you,
Stephen
You must specify both type parameters for method Wrap. That is:
using (var proxy = new PLPlacementServiceClient().Wrap<PLPlacementServiceClient,/*type of the service contract PLPlacementServiceClient is implementing*/>())
{
var result = proxy.BaseObject.GetDocumentClassForNewBusiness();
}
I have a generic delegate like this:
public delegate T SomeHandler<T>(T input);
I have a generic class that take the delegate as a parameter to its constructor like this:
public class SomeClass<T>
{
private SomeHandler<T> m_handler;
public SomeClass(SomeHandler<T> handler)
{
m_handler = handler;
}
public void DoSomeStuff(T input)
{
T result = m_handler(input);
// some stuff
}
}
Most of the time I would instantiate the class with a default handler unless some special case is needed. So I have some default handlers for the types I use:
public static class DefaultHandlers
{
public static string DefaultStringHandler(string input)
{
return input;
}
}
In some cases, the type is instantiated with a special handler that is specific to its implementation:
public class Example
{
private SomeClass<string> m_typicalCase;
private SomeClass<string> m_specialCase;
public Example()
{
m_typicalCase = new SomeClass<string>(DefaultHandlers.DefaultStringHandler);
m_specialCase = new SomeClass<string>(SpecialHandler);
}
private string SpecialHandler(string input)
{
string result;
// Do something special
return result;
}
}
I want to create a default constructor for SomeClass that always instantiates the class with the same default handler for that type, but since the type is not know at compile time, I can't return the delegate that is the right type.
public class SomeClass<T>
{
...
public SomeClass()
{
m_handler = DefaultHandlers.GetDefaultHandler<T>();
}
...
}
Like this
public static class DefaultHandlers
{
public static SomeHandler<T> GetDefaultHandler<T>()
{
if (typeof(T) == typeof(string))
{
return DefaultStringHandler;
}
}
}
This does not work becuase DefaultStringHandler returns a string and the method expects T.
The only way that I have found to do this is the make a type-specific subclass of SomeClass that overloads the default constructor:
public class SomeStringClass : SomeClass<string>
{
public SomeStringClass()
: base(DefaultHandlers.DefaultStringHandler)
{
}
public SomeStringClass(SomeHandler<string> handler)
: base(handler)
{
}
}
It would be fun if generic types could have type-specific overloaded constructors that are used when instantiating the class of a specific type:
public class Foo<T>
{
public Foo<string>(string input)
{
}
public Foo<int>(int input)
{
}
public Foo(T input)
{
}
}
There must be a more elegant way to do with with a design pattern, Strategy maybe?
You could utilize dynamic to get something like SomeClass<string>():
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Zoltan
{
public class SomeClass<T>
{
private static readonly Func<T,T> FALL_BACK_HANDLER = a => a; //or what have you
private readonly Func<T,T> m_handler;
public SomeClass(Func<T,T> handler)
{
m_handler = handler;
}
public SomeClass()
{
m_handler = DefaultHandler.For<T>() ?? FALL_BACK_HANDLER;
}
public void DoSomeStuff(T input)
{
T result = m_handler(input);
Console.WriteLine(result);
}
}
public static class DefaultHandler
{
public static Func<T,T> For<T>()
{
return TypeAware<T>.Default;
}
private static class TypeAware<T>
{
private static readonly Func<T,T> DEFAULT;
static TypeAware()
{
var type = typeof(T);
if (type == typeof(string))
{
DEFAULT = a => DefaultHandler.StringHandler((dynamic) a);
}
else if (type == typeof(int))
{
DEFAULT = a => DefaultHandler.IntHandler((dynamic) a);
}
else
{
DEFAULT = null;
}
}
public static Func<T,T> Default { get { return DEFAULT; } }
}
public static string StringHandler(string a)
{
return a + " The default handler does some stuff!";
}
public static int IntHandler(int a)
{
return a + 2;
}
}
}
You would then consume SomeClass as follows:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Zoltan
{
public class Program
{
public static void Main(string[] args)
{
var someStringObj = new SomeClass<string>();
someStringObj.DoSomeStuff("Hello World.");//prints "Hello World. The default handler does some stuff!"
var someIntObj = new SomeClass<int>();
someIntObj.DoSomeStuff(1);//prints 3
var someCustomDoubleObj = new SomeClass<double>(d => d - 2);
someCustomDoubleObj.DoSomeStuff(3);//prints 1
Console.Read();
}
}
}
Building on Jon Skeet and Alexei Levenkovs comments. From what I understand, something like this might be what you're after?
public delegate T SomeHandler<T>(T input);
public class SomeClass<T>
{
private SomeHandler<T> m_handler;
public SomeClass()
{
m_handler = (T input) => input;
}
public SomeClass(SomeHandler<T> handler)
{
m_handler = handler;
}
public void DoSomeStuff(T input)
{
T result = m_handler(input);
// some stuff
}
}
Another way would be to move the string-specific behaviour into a separate class and simply make an instance of that class if you want specific behaviour tied to a specific type
public delegate T SomeHandler<T>(T input);
public class SomeClass<T>
{
protected SomeHandler<T> m_handler;
protected SomeClass()
{
}
public SomeClass(SomeHandler<T> handler)
{
m_handler = handler;
}
public void DoSomeStuff(T input)
{
T result = m_handler(input);
// some stuff
}
}
public class SomeStringClass : SomeClass<string>
{
public SomeStringClass()
{
m_handler = DefaultStringHandler;
}
private string DefaultStringHandler(string input)
{
// Do default string stuff here...
return input;
}
public SomeStringClass(SomeHandler<string> handler):base(handler)
{
}
}
I have an <asp:Label> I wish to populate depending on the Generic object that I pass to it.
At the moment I have the following code:-
private void PopulateEnglishQuestion(int questionId)
{
ReportQuestion reportQuestion = questionsBll.GetReportQuestions().Where(x=> x.ReportQuestionId == questionId).FirstOrDefault();
PopulateLabels(reportQuestion);
}
private void PopulateTranslatedQuesiton(int questionId)
{
ReportQuestionTranslation reportQuestionTranslation = questionsBll.GetReportQuestionsTranslation().Where(x => x.QuestionId == questionId).FirstOrDefault();
PopulateLabels(reportQuestionTranslation);
}
private void PopulateLabels<T>(T item)
{
lblQuestionTitle.Text = typeof (T) == typeof (ReportQuestion)
? ((ReportQuestion) (item)).ReportQuestionTitle
: ((ReportQuestionTranslation) (item)).ReportQuestionTitleTrans;
}
How can I get the method PopulateLabels to work properly?
You should use an interface both ReportQuestion and ReportQuestionTranslation implement:
interface IQuestion
{
string TitleText;
}
Then, use the following code:
public void PopulateLabels(IQuestion item)
{
lblQuestionTitle.Text = item.TitleText;
}
Use an interface.
public interface IQuestion
{
string Title { get; }
}
public class ReportQuestion : IQuestion
{
public string Title { get { return ReportQuestionTitle; } }
}
public class ReportQuestionTranslation: IQuestion
{
public string Title { get { return ReportQuestionTitleTrans; } }
}
private void PopulateLabels(IQuestion item)
{
lblQuestionTitle.Text = item.Title;
}
Or use method overloading:
public void PopulateTitle(ReportQuestion question)
{
lblQuestionTitle.Text = question.ReportQuestionTitle;
}
public void PopulateTitle(ReportQuestionTranslation question)
{
lblQuestionTitle.Text = question.ReportQuestionTitleTrans;
}
Unrecommended:
public class QuestionTitleFormatter
{
public string GetTitle(object question)
{
if(question is ReportQuestion)
return ((ReportQuestion)question).ReportQuestionTitle;
if(question is ReportQuestionTranslation)
return ((ReportQuestionTranslation)question).ReportQuestionTitleTrans;
throw new NotImplementedException(string.Format("{0} is not supported", questionType.Name);
}
}
public void PopulateTitle(object question)
{
var formatter = new QuestionTitleFormatter();
lblQuestionTitle.Text = formatter.GetTitle(question);
}
The ToString() approach would be something like this:
class ReportQuestion {
public override string ToString() { return ReportQuestionTitle; }
...
}
class ReportQuestionTranslation{
public override string ToString() { return ReportQuestionTitleTrans; }
...
}
assuming that I answered my own question correctly in the comment above asking where the string will come from.
You could just override ToString() on those objects and not worry about any transformations or types in PopulateLabel.
What I'm trying to do is to be able to intercept calls to an object's methods and properties for cross-cutting concerns. I'm using proxy-based AOP using ContextBoundObject.
However this doesn't work for recursive method calls, The first call against the target will be intercepted by the proxy and successfully invoked, allowing me to do cross-cut here. However subsequent method calls from within the first method will stay within the target class and are not intercepted by the proxy as if no marshaling occurs!
Is there any way I can make it work? (I'm trying to avoid third-party libraries like PostSharp, Unity or Spring.Net)
class Program
{
static void Main(string[] args)
{
var t = new SimpleObject();
t.TestMethod1();
}
}
[Intercept]
class SimpleObject : ContextBoundObject
{
public string TestMethod1()
{
return TestMethod2();
}
public string TestMethod2()
{
return "test";
}
}
[AttributeUsage(AttributeTargets.Class)]
public class InterceptAttribute : ContextAttribute, IContributeObjectSink
{
public InterceptAttribute()
: base("Intercept")
{ }
public override bool IsContextOK(Context ctx, IConstructionCallMessage ctorMsg)
{
return false;
}
public IMessageSink GetObjectSink(MarshalByRefObject obj, IMessageSink nextSink)
{
return new InterceptSink(nextSink);
}
}
public class InterceptSink : IMessageSink
{
public IMessageSink NextSink { get; private set; }
public InterceptSink(IMessageSink nextSink)
{
this.NextSink = nextSink;
}
public IMessage SyncProcessMessage(IMessage msg)
{
IMethodCallMessage mcm = (msg as IMethodCallMessage);
// { cross-cut here }
IMessage rtnMsg = this.NextSink.SyncProcessMessage(msg);
IMethodReturnMessage mrm = (rtnMsg as IMethodReturnMessage);
// { cross-cut here }
return mrm;
}
public IMessageCtrl AsyncProcessMessage(IMessage msg, IMessageSink replySink)
{
return null;
}
}
C# designers have never been in favor of AOP, there's no easy way to intercept method calls without using Proxies and Marshaling, which have their own drawbacks!
In case anyone wants to intercept method/property calls (eg. cross cutting concerns), I've found RealProxy to be of some help.
RealProxy From MSDN:
A client that uses an object across any kind of a remoting boundary is
actually using a transparent proxy for the object. The transparent
proxy provides the illusion that the actual object resides in the
client's space. It achieves this by forwarding calls made on it to the
real object using the remoting infrastructure.
Note: A type being proxied using RealProxy must be either an interface or inherit from MarshalByRefObject.
Here's some implementation of RealProxy using a Factory Method to create a proxy of an object at runtime:
public abstract class RuntimeProxy
{
public static readonly object Default = new object();
public static Target Create<Target>(Target instance, RuntimeProxyInterceptor interceptor) where Target : class
{
return (Target)new InternalProxy<Target>(instance, interceptor).GetTransparentProxy();
}
public static Target Create<Target>(Target instance, Func<RuntimeProxyInvoker, object> factory) where Target : class
{
return (Target)new InternalProxy<Target>(instance, new InternalRuntimeProxyInterceptor(factory)).GetTransparentProxy();
}
class InternalProxy<Target> : RealProxy where Target : class
{
readonly object Instance;
readonly RuntimeProxyInterceptor Interceptor;
public InternalProxy(Target instance, RuntimeProxyInterceptor interceptor)
: base(typeof(Target))
{
Instance = instance;
Interceptor = interceptor;
}
public override IMessage Invoke(IMessage msg)
{
var methodCall = (IMethodCallMessage)msg;
var method = (MethodInfo)methodCall.MethodBase;
try
{
var result = Interceptor.Invoke(new InternalRuntimeProxyInterceptorInvoker(Instance, method, methodCall.InArgs));
if (result == RuntimeProxy.Default)
result = method.ReturnType.IsPrimitive ? Activator.CreateInstance(method.ReturnType) : null;
return new ReturnMessage(result, null, 0, methodCall.LogicalCallContext, methodCall);
}
catch (Exception ex)
{
if (ex is TargetInvocationException && ex.InnerException != null)
return new ReturnMessage(ex.InnerException, msg as IMethodCallMessage);
return new ReturnMessage(ex, msg as IMethodCallMessage);
}
}
}
class InternalRuntimeProxyInterceptor : RuntimeProxyInterceptor
{
readonly Func<RuntimeProxyInvoker, object> Factory;
public InternalRuntimeProxyInterceptor(Func<RuntimeProxyInvoker, object> factory)
{
this.Factory = factory;
}
public override object Invoke(RuntimeProxyInvoker invoker)
{
return Factory(invoker);
}
}
class InternalRuntimeProxyInterceptorInvoker : RuntimeProxyInvoker
{
public InternalRuntimeProxyInterceptorInvoker(object target, MethodInfo method, object[] args)
: base(target, method, args)
{ }
}
}
public abstract class RuntimeProxyInterceptor
{
public virtual object Invoke(RuntimeProxyInvoker invoker)
{
return invoker.Invoke();
}
}
public abstract class RuntimeProxyInvoker
{
public readonly object Target;
public readonly MethodInfo Method;
public readonly ReadOnlyCollection<object> Arguments;
public RuntimeProxyInvoker(object target, MethodInfo method, object[] args)
{
this.Target = target;
this.Method = method;
this.Arguments = new ReadOnlyCollection<object>(args);
}
public object Invoke()
{
return Invoke(this.Target);
}
public object Invoke(object target)
{
if (target == null)
throw new ArgumentNullException("target");
try
{
return this.Method.Invoke(target, this.Arguments.ToArray());
}
catch (TargetInvocationException ex)
{
throw ex.InnerException;
}
}
}
You can use the RuntimeProxy as a factory to create a proxy of an object and intercept all method/property calls and invoke the actual method.
Here's a sample:
class SomeClass : MarshalByRefObject
{
public int Mul(int a, int b)
{
return a * b;
}
public void SetValue(int val)
{
this.Val = val;
}
public int Val { get; set; }
}
Use RuntimeProxy class to create a proxy for an instance of the SomeClass class and intercept the calls:
var test = new SomeClass();
var proxy = RuntimeProxy.Create(test, t =>
{
// cross-cut here
return t.Invoke(); // invoke the actual call
});
var res = proxy.Mul(3, 4); // method with return value
proxy.SetValue(2); // void method, setting some property
var val = proxy.Val; // property access
You could use interface types in case you don't want to inherit from MarshalByRefObject class.