Update
I solved this problem with the following code, but it's not the solution I'm looking for. This is still an open bounty for a more generic solution. If we ever have a table that isn't an int or string for the key value we'll have to add to this manually to make it work.
c.For(typeof(ILogDifferencesCommand<,>)).Use(typeof(LogDifferencesCommand<,>))
.Ctor<ILogDifferencesLogger<int>>()
.Named(AppSettingsManager.Get("logDifferences:Target"))
.Ctor<string>()
.Named(AppSettingsManager.Get("logDifferences:Target"));
Original Question
I have three types of loggers, and I've defined named instances in my container for them:
c.For(typeof(ILogDifferencesLogger<>))
.Use(typeof(LogDifferencesAllLogger<>))
.Named("all");
c.For(typeof(ILogDifferencesLogger<>))
.Use(typeof(LogDifferencesNLogLogger<>))
.Named("nlog");
c.For(typeof(ILogDifferencesLogger<>))
.Use(typeof(LogDifferencesDatabaseLogger<>))
.Named("database");
The LogDifferencesCommand receives an ILogDifferencesLogger<> as its only argument:
public LogDifferencesCommand(ILogDifferencesLogger<TKey> logDifferencesLogger)
{
this.logDifferencesLogger = logDifferencesLogger;
}
How do I properly configure the ILogDifferencesCommand<> to grab the right named instance based off of an application setting? Right now I've got something like this:
c.For(typeof(ILogDifferencesCommand<,>))
.Use(typeof(LogDifferencesCommand<,>));
The issue I'm having is I can't pull in the Ctor<> because I can't use unbound generics with that signature, so then I can't use the Named method off the Ctor for that.
For example, I could do something like this, but that wouldn't hit all possible types:
c.For(typeof(ILogDifferencesCommand<,>)).Use(typeof(LogDifferencesCommand<,>))
.Ctor<ILogDifferencesLogger<int>>()
.Named(AppSettingsManager.Get("logDifferences:Target"));
But the problem then is I'd have to handle every TKey type the system uses.
Class and Interface Definitions
public class LogDifferencesCommand<TModel, TKey> : ILogDifferencesCommand<TModel, TKey>
where TModel : class, IIdModel<TKey>
{
public LogDifferencesCommand(ILogDifferencesLogger<TKey> logDifferencesLogger)
{
this.logDifferencesLogger = logDifferencesLogger;
}
}
public interface ILogDifferencesCommand<TModel, TKey>
where TModel : class, IIdModel<TKey>
{
List<LogDifference> CalculateDifferences(TModel x, TModel y);
void LogDifferences(TModel x, TModel y, string tableName, string keyField, string userId, int? clientId);
void RegisterCustomDisplayNameObserver(WeakReference<ICustomDisplayNameObserver<TModel>> observer);
void RegisterCustomChangeDateObserver(WeakReference<ICustomChangeDateObserver<TModel>> observer);
}
public interface ILogDifferencesLogger<TKey>
{
void LogDifferences(string tableName, string keyField, string userId, TKey id, List<LogDifference> differences, int? clientId);
}
The reason TKey is required is because of the IIdModel interface.
One option that comes to mind:
var loggers = new Dictionary<string, ConfiguredInstance>();
loggers.Add("all", c.For(typeof(ILogDifferencesLogger<>))
.Use(typeof(LogDifferencesAllLogger<>)));
loggers.Add("nlog", c.For(typeof(ILogDifferencesLogger<>))
.Use(typeof(LogDifferencesNLogLogger<>)));
loggers.Add("database", c.For(typeof(ILogDifferencesLogger<>))
.Use(typeof(LogDifferencesDatabaseLogger<>)));
foreach (var kv in loggers) {
// if you still need them named
// if you only used names for this concrete scenario - you probably don't
// so can remove it
kv.Value.Named(kv.Key);
}
c.For(typeof(LogDifferencesCommand<>))
.Use(typeof(LogDifferencesCommand<>))
// add explicit instance as dependency
.Dependencies.Add(typeof(ILogDifferencesLogger<>), loggers[AppSettingsManager.Get("logDifferences:Target")]);
Update. As we've figured out in comments, this doesn't work for your specific case when LogDifferencesCommand has multiple type arguments. For some reason (and I think it's a bug) - structure map tries to create closed generic type ILogDifferencesLogger<>, but when doing that - passes generic type arguments from LogDifferencesCommand. Maybe worth firing an issue at their github. You can workaround it like this:
public class GenericTypesWorkaroundInstance : Instance
{
private readonly Instance _target;
private readonly Func<Type[], Type[]> _chooseTypes;
public GenericTypesWorkaroundInstance(Instance target, Func<Type[], Type[]> chooseTypes) {
_target = target;
_chooseTypes = chooseTypes;
ReturnedType = _target.ReturnedType;
}
public override Instance CloseType(Type[] types) {
// close type correctly by ignoring wrong type arguments
return _target.CloseType(_chooseTypes(types));
}
public override IDependencySource ToDependencySource(Type pluginType) {
throw new NotSupportedException();
}
public override string Description => "Correctly close types over open generic instance";
public override Type ReturnedType { get; }
}
And then doing
commandReg.Dependencies.Add(
commandReg.Constructor.GetParameters().First(
p => p.ParameterType.IsGenericType && p.ParameterType.GetGenericTypeDefinition() == typeof(ILogDifferencesLogger<>)).Name,
new GenericTypesWorkaroundInstance(
loggers[AppSettingsManager.Get("logDifferences:Target")],
// specify which types are correct
types => types.Skip(1).ToArray()));
And it works, but I cannot say that I like it.
The author of StructureMap (me) would strongly advise you try to use conditional registration upfront at application bootstrapping time to select the default logger registrations by checking the configuration value and then just allowing auto-wiring to handle the dependencies at runtime.
Related
I have a situation where in, I would like to convert an Expression<Func<BaseType,object>> to Expression<Func<DerievedType,object>>
I am also open to other solutions as well for this particular scenario.
To demonstrate the problem, i have base class as following
public class PersonBase
{
public string Name{get;set;}
public virtual void Save()
{
Dummy.Method1(this,x=>x.Name);
}
}
Derieved Class is defined as
public class Student:PersonBase
{
public string School{get;set;}
}
The Dummy class and associated methods are defined as
public class Dummy
{
public static void Method1<TDestination>(TDestination value,params Expression<Func<TDestination,object>>[] selector)
{
var destinationType = value.GetType();
var selectorType = selector.GetType();
Console.WriteLine("Destination Type : " + destinationType.ToString());
Console.WriteLine("Selector Type : " +selectorType.ToString());
var FinalMethodToCallInfo = typeof(Dummy).GetMethod("FinalMethodToCall", BindingFlags.Public | BindingFlags.Static);
var FinalMethodToCallMethod = FinalMethodToCallInfo.MakeGenericMethod(destinationType);
FinalMethodToCallMethod.Invoke(null, new object[] { selector });
}
public static void FinalMethodToCall<TDestination>(params Expression<Func<TDestination,object>>[] selector)
{
Console.WriteLine("Finally here");
}
}
The whole example is demonstrated in the Fiddle here.
Since the destinationType in Method1 is of Type Student and selectorType is of type Expression>, I get an exception when i attempt to invoke the FinalMethodToCall using reflection.
Object of type 'System.Linq.Expressions.Expression`1[System.Func`2[PersonBase,System.Object]][]' cannot be converted to type 'System.Linq.Expressions.Expression`1[System.Func`2[Student,System.Object]][]'.
I am slightly lost here. One solution I could think of was to use ExpressionVisitor to replace the Expression Parameter Type from BaseClass to DerievedType.
But I was curious to know why, when calling the method from Base (and passing expression), I was pointing to two different types (Derieved and Base). Could someone guide me in understanding this behavior and also if there is a better solution than using ExpressionVisitor to replace the Parameter Type ?
PS: I cannot change signature of my Save Method.
I have made few changes to generic methods as below.
Update PersonBase and make Save method to explicitly declare T.
public class PersonBase
{
public string Name{get;set;}
public virtual void Save<T>() where T : PersonBase
{
Dummy.Method1<T>(this,x=>x.Name);
}
}
Update Method1's first parameter to be Object like below.
public static void Method1<TDestination>(Object value,params Expression<Func<TDestination,object>>[] selector)
And call your Save with explicitly passing generic value like as follow.
(new Student{Name="anu"}).Save<Student>();
I am implementing a type of factory pattern and found this neat-looking pattern on Code Review.
I've implemented this solution with some variations as follows:
I have a factory class which looks like this:
public class SearchableServiceFactory<TSearchableLookupService, TOutputDto>
where TOutputDto : IBaseOutputDto
where TSearchableLookupService : ISearchableLookupService<TOutputDto>
{
static readonly Dictionary<string, Func<TSearchableLookupService>> _SearchableLookupServicesRegistry =
new Dictionary<string, Func<TSearchableLookupService>>();
private SearchableServiceFactory() { }
public static TSearchableLookupService Create(string key)
{
if (_SearchableLookupServicesRegistry.TryGetValue(
key, out Func<TSearchableLookupService> searchableServiceConstructor)
)
return searchableServiceConstructor();
throw new NotImplementedException();
}
public static void Register<TDerivedSearchableService>
(
string key,
Func<TSearchableLookupService> searchableServiceConstructor
)
where TDerivedSearchableService : TSearchableLookupService
{
var serviceType = typeof(TDerivedSearchableService);
if (serviceType.IsInterface || serviceType.IsAbstract)
throw new NotImplementedException();
_SearchableLookupServicesRegistry.Add(key, searchableServiceConstructor);
}
That works. I call it from code, thus:
...
SearchableServiceFactory<OrgLookupService, OrgOutputDto>.Register<OrgLookupService>
(
nameof(Organization), () => new OrgLookupService(_Context, _OrganizationRepository)
);
...
That works. A constructor is added to the dictionary, along with a key. Then I go to retrieve that constructor by key, to get an instance and do something with it, like so:
SearchableServiceFactory<ISearchableLookupService<IBaseOutputDto>, IBaseOutputDto>.Create(myKey).DoAThing();
That fails because no such value exists in the dictionary. Because it's static, as are the methods in the class that register and create the instances I need.
I'm using .NET Core 2.1, if that matters (this seems like a strictly C# issue).
SearchableServiceFactory<OrgLookupService, OrgOutputDto> is not the same type as SearchableServiceFactory<ISearchableLookupService<IBaseOutputDto>, IBaseOutputDto>, and as such, even the static properties are different.
They are different types in the eyes of the compiler. Just because OrglookupService is a ISearchableLookupService, not every ISearchableLookupService is a OrglookupService.
A possible workaround would be to use SearchableServiceFactory<ISearchableLookupService<IBaseOutputDto>, IBaseOutputDto> to register your object, but that would require the ISearchableLookupService to be covariant.
public interface ISearchableLookupService<out TOutputDto>
where TOutputDto : IBaseOutputDto
{
}
And register like this:
SearchableServiceFactory<ISearchableLookupService<IBaseOutputDto>, IBaseOutputDto>.Register<OrgLookupService>
(
nameof(Organization), () => new OrgLookupService()
);
The class SearchableServiceFactory<A, B> is not the same class as
SearchableServiceFactory<X, Y>. Therefore, you are dealing with two distinct sets of static members. Particularly, you have two different dictionaries _SearchableLookupServicesRegistry.
You are registering into one of them (in SearchableServiceFactory<OrgLookupService, OrgOutputDto>). The other one (in
SearchableServiceFactory<ISearchableLookupService<IBaseOutputDto>, IBaseOutputDto>) remains empty, but you are trying to use it for the retrieval of the constructor. If you set a breakpoint on the throw statement in Create and inspect _SearchableLookupServicesRegistry, you will see that its Count is 0.
The problem with generics is that they may appear to offer some dynamic behavior, but they do not. All generic type parameters are determined a compile time. Complex scenarios using generics often tend to become highly convoluted. If you need to be highly dynamic, you must sometimes give up full type safety.
This is my suggestion for a service factory:
public static class SearchableServiceFactory
{
static readonly Dictionary<string, Func<ISearchableLookupService<IBaseOutputDto>>>
_SearchableLookupServicesRegistry =
new Dictionary<string, Func<ISearchableLookupService<IBaseOutputDto>>>();
public static TSearchableLookupService Create<TSearchableLookupService>(string key)
where TSearchableLookupService : ISearchableLookupService<IBaseOutputDto>
{
if (_SearchableLookupServicesRegistry.TryGetValue(
key,
out Func<ISearchableLookupService<IBaseOutputDto>> searchableServiceConstructor))
{
return (TSearchableLookupService)searchableServiceConstructor();
}
throw new ArgumentException($"Service for \"{key}\" not registered.");
}
public static void Register(
string key,
Func<ISearchableLookupService<IBaseOutputDto>> searchableServiceConstructor)
{
_SearchableLookupServicesRegistry.Add(key, searchableServiceConstructor);
}
}
Note that SearchableServiceFactory is not generic. This is necessary to have only one single factory and consequently only one static dictionary.
It uses this modified interface having an out modifier. The out modifier adds covariance. I.e., you can supply a derived type for it; however, the generic type decorated with it must only occur as return type or in out parameters.
public interface ISearchableLookupService<out TOutputDto> where TOutputDto : IBaseOutputDto
{
TOutputDto GetOutputDto();
}
You can register with
SearchableServiceFactory.Register(
nameof(Organization), () => new OrgLookupService(_Context, _OrganizationRepository));
and create with
IBaseOutputDto result = SearchableServiceFactory
.Create<ISearchableLookupService<IBaseOutputDto>>(nameof(Organization))
.GetOutputDto();
or to get a more concrete type
OrgOutputDto result = SearchableServiceFactory
.Create<ISearchableLookupService<OrgOutputDto>>(nameof(Organization))
.GetOutputDto();
But this last example makes the string key nameof(Organization) redundant, as the type of OrgOutputDto itself could be used as key. (I would require some Reflection to extract it from TSearchableLookupService.)
I've something along this lines:
public class Something
{
private IDictionary<object,Activity> fCases;
public IDictionary<object,Activity> Cases
{
get { return fCases; }
set { fCases = value; }
}
}
public sealed class Something<T> : Something
{
private IDictionary<T,Activity> fCases;
public override IDictionary<T,Activity> Cases
{
get { return fCases; }
set { fCases = value; }
}
}
Note: override is not accepted on this case
Due to heavy Reflection usage there are situations where I've to downcast from Something<T> to Something but, I guess because Cases property is hidden, I'm losing Cases data.
How can I circumvent this situation? I've tried to use where T:object but that isn't accepted also.
EDIT:
This is an example of why I need inheritance:
if (someVar is Something) {
if (someVar.GetType().IsGenericType)
{
// Construct AnotherObject<T> depending on the Something<T>'s generic argument
Type typeArg = someVar.GetType().GetGenericArguments()[0],
genericDefinition = typeof(AnotherObject<>),
typeToConstruct = genericDefinition.makeGenericType(typeArgs);
object newAnotherObject = Activator.CreateInstance(typeToConstruct);
// Pass Something 'Cases' property to AnotherObject<T>
constructedType.InvokeMember(
"Cases",
BindingFlags.Instance | BindingFlags.Public | BindingFlags.SetProperty,
null,
newActivity,
new Object[] { someVar.Cases });
}
}
But, because 'Cases' is hidden, it will be always null. Without inheritance I would have to write a BIG if-then-else with all the possible generic arguments. And, believe me, I do really have to use someVar is Something and Reflection to construct all this objects. This is a big generic API being converted to other big generic API and so they should not known each other and the conversion should be as transparent as possible.
You won't be able to override it like that, and for good reason.
Imagine:
Something x = new Something<string>();
Button key = new Button();
x.Cases[key] = new Activity();
If your override worked, that would be trying to store a Button reference as a key in Dictionary<string, Activity>. That would be a Bad Thing.
Perhaps inheritance isn't actually appropriate in this case? If you could explain more about what you're trying to achieve, that would help. Perhaps you don't really need the dictionary as a property? Maybe just a method to fetch by key?
This is flat-out not going to work because the IDictionary<TKey, TValue> interface is invariant. An IDictionary<object, Activity> cannot be treated as an IDictionary<T, Activity>.
What you could do, rather than exposing an entire IDictionary<T, Activity> in your derived class, is simply delegate the calls you want to expose, like this:
public class Something
{
protected IDictionary<object, Activity> Cases { get; set; }
}
public sealed class Something<T> : Something
{
public Activity GetCase(T key)
{
return Cases[key];
}
public void AddCase(T key, Activity case)
{
Cases.Add(key, case);
}
// etc. etc.
}
Alternatively, you could also define your own contravariant interface, something like:
interface IKeyedCollection<in TKey, TValue>
{
TValue this[TKey key] { get; set; }
void Add(TKey key, TValue value);
}
For the above interface, an IKeyedCollection<object, Activity> could act as an IKeyedCollection<T, Activity> because every T is an object.
If you attempt to expose incompatible types at the different levels you're going to keep running into problems because at the end of the day you'll end up having to maintain 2 separate objects (or 1 custom object with 2 interfaces it can't completely satisfy).
These types are incompatible because there are values which can be added to IDictionary<object, Activity> which cannot be added to every instantiation of IDictionary<T, Activity>. Imagine for instance T is instatiated as string and the developer uses a int key elsewhere via Something. This creates a real problem for Something<string> implementations.
The way I would approach this is to change the base type Something to not expose a concrete type but instead to expose the relevant APIs.
public abstract class Something {
public abstract IEnumerable<KeyValuePair> GetElements();
public abstract bool TryGetValue(object key, out Activity value);
}
This gives Something<T> the flexbility it needs to properly sub-class Something and be very expressive about the types it wants to expose
public sealed class Something<T> : Something {
private IDictionary<T,Activity> fCases;
public override IDictionary<T,Activity> Cases
{
get { return fCases; }
set { fCases = value; }
}
public override IEnumerable<KeyValuPair<object, Activity>> GetElements() {
foreach (var cur in fCases) {
yield return new KeyValuePair<object, Activity>(cur.Key, cur.Value);
}
}
public override bool TryGetValue(object key, out Activity activity) {
try {
T typedKey = (T)key;
return fCases.TryGetValue(typedKey, out activity);
} catch (InvalidCastException) {
activity = null;
return false;
}
}
}
}
During heavy reflection usage I also had the need to 'upcast' from generic types. I knew certain calls would be compatible, but I didn't know the types at compile time. If you look at it this way, it is not really 'upcasting' a generic type, but rather, allowing to use generics during reflection by generating the correct downcasts.
To this end I created a helper method to create delegates along the lines of Delegate.CreateDelegate, but allowing to create a less generic delegate. Downcasts are generated where necessary. I explain it in detail on my blog.
MethodInfo methodToCall = typeof( string ).GetMethod( "Compare" );
Func<object, object, int> unknownArgument
= DelegateHelper.CreateDowncastingDelegate<Func<object, object, int>>(
null, methodToCall );
unknownArgument( "test", "test" ); // Will return 0.
unknownArgument( "test", 1 ); // Will compile, but throw InvalidCastException.
A bit later I had a need to create entire less generic wrapper classes for generic classes, so that all method calls would immediately become available as less generic calls during reflection. This might or might not be useful in your scenario as well. For this purpose I created a (not as thoroughly tested) method which allows to generate this wrapper class at runtime using emit. It is available in my open source library. I haven't written about this yet, so when interested you'll just have to try it out (and possibly see it fail since it's still quite new).
I asked a question yesterday regarding using either reflection or Strategy Pattern for dynamically calling methods.
However, since then I have decided to change the methods into individual classes that implement a common interface. The reason being, each class, whilst bearing some similarities also perform certain methods unique to that class.
I had been using a strategy as such:
switch (method)
{
case "Pivot":
return new Pivot(originalData);
case "GroupBy":
return new GroupBy(originalData);
case "Standard deviation":
return new StandardDeviation(originalData);
case "% phospho PRAS Protein":
return new PhosphoPRASPercentage(originalData);
case "AveragePPPperTreatment":
return new AveragePPPperTreatment(originalData);
case "AvgPPPNControl":
return new AvgPPPNControl(originalData);
case "PercentageInhibition":
return new PercentageInhibition(originalData);
default:
throw new Exception("ERROR: Method " + method + " does not exist.");
}
However, as the number of potential classes grow, I will need to keep adding new ones, thus breaking the closed for modification rule.
Instead, I have used a solution as such:
var test = Activator.CreateInstance(null, "MBDDXDataViews."+ _class);
ICalculation instance = (ICalculation)test.Unwrap();
return instance;
Effectively, the _class parameter is the name of the class passed in at runtime.
Is this a common way to do this, will there be any performance issues with this?
I am fairly new to reflection, so your advice would be welcome.
When using reflection you should ask yourself a couple of questions first, because you may end up in an over-the-top complex solution that's hard to maintain:
Is there a way to solve the problem using genericity or class/interface inheritance?
Can I solve the problem using dynamic invocations (only .NET 4.0 and above)?
Is performance important, i.e. will my reflected method or instantiation call be called once, twice or a million times?
Can I combine technologies to get to a smart but workable/understandable solution?
Am I ok with losing compile time type safety?
Genericity / dynamic
From your description I assume you do not know the types at compile time, you only know they share the interface ICalculation. If this is correct, then number (1) and (2) above are likely not possible in your scenario.
Performance
This is an important question to ask. The overhead of using reflection can impede a more than 400-fold penalty: that slows down even a moderate amount of calls.
The resolution is relatively easy: instead of using Activator.CreateInstance, use a factory method (you already have that), look up the MethodInfo create a delegate, cache it and use the delegate from then on. This yields only a penalty on the first invocation, subsequent invocations have near-native performance.
Combine technologies
A lot is possible here, but I'd really need to know more of your situation to assist in this direction. Often, I end up combining dynamic with generics, with cached reflection. When using information hiding (as is normal in OOP), you may end up with a fast, stable and still well-extensible solution.
Losing compile time type safety
Of the five questions, this is perhaps the most important one to worry about. It is very important to create your own exceptions that give clear information about reflection mistakes. That means: every call to a method, constructor or property based on an input string or otherwise unchecked information must be wrapped in a try/catch. Catch only specific exceptions (as always, I mean: never catch Exception itself).
Focus on TargetException (method does not exist), TargetInvocationException (method exists, but rose an exc. when invoked), TargetParameterCountException, MethodAccessException (not the right privileges, happens a lot in ASP.NET), InvalidOperationException (happens with generic types). You don't always need to try to catch all of them, it depends on the expected input and expected target objects.
To sum it up
Get rid of your Activator.CreateInstance and use MethodInfo to find the factory-create method, and use Delegate.CreateDelegate to create and cache the delegate. Simply store it in a static Dictionary where the key is equal to the class-string in your example code. Below is a quick but not-so-dirty way of doing this safely and without losing too much type safety.
Sample code
public class TestDynamicFactory
{
// static storage
private static Dictionary<string, Func<ICalculate>> InstanceCreateCache = new Dictionary<string, Func<ICalculate>>();
// how to invoke it
static int Main()
{
// invoke it, this is lightning fast and the first-time cache will be arranged
// also, no need to give the full method anymore, just the classname, as we
// use an interface for the rest. Almost full type safety!
ICalculate instanceOfCalculator = this.CreateCachableICalculate("RandomNumber");
int result = instanceOfCalculator.ExecuteCalculation();
}
// searches for the class, initiates it (calls factory method) and returns the instance
// TODO: add a lot of error handling!
ICalculate CreateCachableICalculate(string className)
{
if(!InstanceCreateCache.ContainsKey(className))
{
// get the type (several ways exist, this is an eays one)
Type type = TypeDelegator.GetType("TestDynamicFactory." + className);
// NOTE: this can be tempting, but do NOT use the following, because you cannot
// create a delegate from a ctor and will loose many performance benefits
//ConstructorInfo constructorInfo = type.GetConstructor(Type.EmptyTypes);
// works with public instance/static methods
MethodInfo mi = type.GetMethod("Create");
// the "magic", turn it into a delegate
var createInstanceDelegate = (Func<ICalculate>) Delegate.CreateDelegate(typeof (Func<ICalculate>), mi);
// store for future reference
InstanceCreateCache.Add(className, createInstanceDelegate);
}
return InstanceCreateCache[className].Invoke();
}
}
// example of your ICalculate interface
public interface ICalculate
{
void Initialize();
int ExecuteCalculation();
}
// example of an ICalculate class
public class RandomNumber : ICalculate
{
private static Random _random;
public static RandomNumber Create()
{
var random = new RandomNumber();
random.Initialize();
return random;
}
public void Initialize()
{
_random = new Random(DateTime.Now.Millisecond);
}
public int ExecuteCalculation()
{
return _random.Next();
}
}
I suggest you give your factory implementation a method RegisterImplementation. So every new class is just a call to that method and you are not changing your factories code.
UPDATE:
What I mean is something like this:
Create an interface that defines a calculation. According to your code, you already did this. For the sake of being complete, I am going to use the following interface in the rest of my answer:
public interface ICalculation
{
void Initialize(string originalData);
void DoWork();
}
Your factory will look something like this:
public class CalculationFactory
{
private readonly Dictionary<string, Func<string, ICalculation>> _calculations =
new Dictionary<string, Func<string, ICalculation>>();
public void RegisterCalculation<T>(string method)
where T : ICalculation, new()
{
_calculations.Add(method, originalData =>
{
var calculation = new T();
calculation.Initialize(originalData);
return calculation;
});
}
public ICalculation CreateInstance(string method, string originalData)
{
return _calculations[method](originalData);
}
}
This simple factory class is lacking error checking for the reason of simplicity.
UPDATE 2:
You would initialize it like this somewhere in your applications initialization routine:
CalculationFactory _factory = new CalculationFactory();
public void RegisterCalculations()
{
_factory.RegisterCalculation<Pivot>("Pivot");
_factory.RegisterCalculation<GroupBy>("GroupBy");
_factory.RegisterCalculation<StandardDeviation>("Standard deviation");
_factory.RegisterCalculation<PhosphoPRASPercentage>("% phospho PRAS Protein");
_factory.RegisterCalculation<AveragePPPperTreatment>("AveragePPPperTreatment");
_factory.RegisterCalculation<AvgPPPNControl>("AvgPPPNControl");
_factory.RegisterCalculation<PercentageInhibition>("PercentageInhibition");
}
Just as an example how to add initialization in the constructor:
Something similar to: Activator.CreateInstance(Type.GetType("ConsoleApplication1.Operation1"), initializationData);
but written with Linq Expression, part of code is taken here:
public class Operation1
{
public Operation1(object data)
{
}
}
public class Operation2
{
public Operation2(object data)
{
}
}
public class ActivatorsStorage
{
public delegate object ObjectActivator(params object[] args);
private readonly Dictionary<string, ObjectActivator> activators = new Dictionary<string,ObjectActivator>();
private ObjectActivator CreateActivator(ConstructorInfo ctor)
{
Type type = ctor.DeclaringType;
ParameterInfo[] paramsInfo = ctor.GetParameters();
ParameterExpression param = Expression.Parameter(typeof(object[]), "args");
Expression[] argsExp = new Expression[paramsInfo.Length];
for (int i = 0; i < paramsInfo.Length; i++)
{
Expression index = Expression.Constant(i);
Type paramType = paramsInfo[i].ParameterType;
Expression paramAccessorExp = Expression.ArrayIndex(param, index);
Expression paramCastExp = Expression.Convert(paramAccessorExp, paramType);
argsExp[i] = paramCastExp;
}
NewExpression newExp = Expression.New(ctor, argsExp);
LambdaExpression lambda = Expression.Lambda(typeof(ObjectActivator), newExp, param);
return (ObjectActivator)lambda.Compile();
}
private ObjectActivator CreateActivator(string className)
{
Type type = Type.GetType(className);
if (type == null)
throw new ArgumentException("Incorrect class name", "className");
// Get contructor with one parameter
ConstructorInfo ctor = type.GetConstructors()
.SingleOrDefault(w => w.GetParameters().Length == 1
&& w.GetParameters()[0].ParameterType == typeof(object));
if (ctor == null)
throw new Exception("There is no any constructor with 1 object parameter.");
return CreateActivator(ctor);
}
public ObjectActivator GetActivator(string className)
{
ObjectActivator activator;
if (activators.TryGetValue(className, out activator))
{
return activator;
}
activator = CreateActivator(className);
activators[className] = activator;
return activator;
}
}
The usage is following:
ActivatorsStorage ast = new ActivatorsStorage();
var a = ast.GetActivator("ConsoleApplication1.Operation1")(initializationData);
var b = ast.GetActivator("ConsoleApplication1.Operation2")(initializationData);
The same can be implemented with DynamicMethods.
Also, the classes are not required to be inherited from the same interface or base class.
Thanks, Vitaliy
One strategy that I use in cases like this is to flag my various implementations with a special attribute to indicate its key, and scan the active assemblies for types with that key:
[AttributeUsage(AttributeTargets.Class)]
public class OperationAttribute : System.Attribute
{
public OperationAttribute(string opKey)
{
_opKey = opKey;
}
private string _opKey;
public string OpKey {get {return _opKey;}}
}
[Operation("Standard deviation")]
public class StandardDeviation : IOperation
{
public void Initialize(object originalData)
{
//...
}
}
public interface IOperation
{
void Initialize(object originalData);
}
public class OperationFactory
{
static OperationFactory()
{
_opTypesByKey =
(from a in AppDomain.CurrentDomain.GetAssemblies()
from t in a.GetTypes()
let att = t.GetCustomAttributes(typeof(OperationAttribute), false).FirstOrDefault()
where att != null
select new { ((OperationAttribute)att).OpKey, t})
.ToDictionary(e => e.OpKey, e => e.t);
}
private static IDictionary<string, Type> _opTypesByKey;
public IOperation GetOperation(string opKey, object originalData)
{
var op = (IOperation)Activator.CreateInstance(_opTypesByKey[opKey]);
op.Initialize(originalData);
return op;
}
}
That way, just by creating a new class with a new key string, you can automatically "plug in" to the factory, without having to modify the factory code at all.
You'll also notice that rather than depending on each implementation to provide a specific constructor, I've created an Initialize method on the interface I expect the classes to implement. As long as they implement the interface, I'll be able to send the "originalData" to them without any reflection weirdness.
I'd also suggest using a dependency injection framework like Ninject instead of using Activator.CreateInstance. That way, your operation implementations can use constructor injection for their various dependencies.
Essentially, it sounds like you want the factory pattern. In this situation, you define a mapping of input to output types and then instantiate the type at runtime like you are doing.
Example:
You have X number of classes, and they all share a common interface of IDoSomething.
public interface IDoSomething
{
void DoSomething();
}
public class Foo : IDoSomething
{
public void DoSomething()
{
// Does Something specific to Foo
}
}
public class Bar : IDoSomething
{
public void DoSomething()
{
// Does something specific to Bar
}
}
public class MyClassFactory
{
private static Dictionary<string, Type> _mapping = new Dictionary<string, Type>();
static MyClassFactory()
{
_mapping.Add("Foo", typeof(Foo));
_mapping.Add("Bar", typeof(Bar));
}
public static void AddMapping(string query, Type concreteType)
{
// Omitting key checking code, etc. Basically, you can register new types at runtime as well.
_mapping.Add(query, concreteType);
}
public IDoSomething GetMySomething(string desiredThing)
{
if(!_mapping.ContainsKey(desiredThing))
throw new ApplicationException("No mapping is defined for: " + desiredThing);
return Activator.CreateInstance(_mapping[desiredThing]) as IDoSomething;
}
}
There's no error checking here. Are you absolutely sure that _class will resolve to a valid class? Are you controlling all the possible values or does this string somehow get populated by an end-user?
Reflection is generally most costly than avoiding it. Performance issues are proportionate to the number of objects you plan to instantiate this way.
Before you run off and use a dependency injection framework read the criticisms of it. =)
I am working on rewriting my fluent interface for my IoC class library, and when I refactored some code in order to share some common functionality through a base class, I hit upon a snag.
Note: This is something I want to do, not something I have to do. If I have to make do with a different syntax, I will, but if anyone has an idea on how to make my code compile the way I want it, it would be most welcome.
I want some extension methods to be available for a specific base-class, and these methods should be generic, with one generic type, related to an argument to the method, but the methods should also return a specific type related to the particular descendant they're invoked upon.
Better with a code example than the above description methinks.
Here's a simple and complete example of what doesn't work:
using System;
namespace ConsoleApplication16
{
public class ParameterizedRegistrationBase { }
public class ConcreteTypeRegistration : ParameterizedRegistrationBase
{
public void SomethingConcrete() { }
}
public class DelegateRegistration : ParameterizedRegistrationBase
{
public void SomethingDelegated() { }
}
public static class Extensions
{
public static ParameterizedRegistrationBase Parameter<T>(
this ParameterizedRegistrationBase p, string name, T value)
{
return p;
}
}
class Program
{
static void Main(string[] args)
{
ConcreteTypeRegistration ct = new ConcreteTypeRegistration();
ct
.Parameter<int>("age", 20)
.SomethingConcrete(); // <-- this is not available
DelegateRegistration del = new DelegateRegistration();
del
.Parameter<int>("age", 20)
.SomethingDelegated(); // <-- neither is this
}
}
}
If you compile this, you'll get:
'ConsoleApplication16.ParameterizedRegistrationBase' does not contain a definition for 'SomethingConcrete' and no extension method 'SomethingConcrete'...
'ConsoleApplication16.ParameterizedRegistrationBase' does not contain a definition for 'SomethingDelegated' and no extension method 'SomethingDelegated'...
What I want is for the extension method (Parameter<T>) to be able to be invoked on both ConcreteTypeRegistration and DelegateRegistration, and in both cases the return type should match the type the extension was invoked on.
The problem is as follows:
I would like to write:
ct.Parameter<string>("name", "Lasse")
^------^
notice only one generic argument
but also that Parameter<T> returns an object of the same type it was invoked on, which means:
ct.Parameter<string>("name", "Lasse").SomethingConcrete();
^ ^-------+-------^
| |
+---------------------------------------------+
.SomethingConcrete comes from the object in "ct"
which in this case is of type ConcreteTypeRegistration
Is there any way I can trick the compiler into making this leap for me?
If I add two generic type arguments to the Parameter method, type inference forces me to either provide both, or none, which means this:
public static TReg Parameter<TReg, T>(
this TReg p, string name, T value)
where TReg : ParameterizedRegistrationBase
gives me this:
Using the generic method 'ConsoleApplication16.Extensions.Parameter<TReg,T>(TReg, string, T)' requires 2 type arguments
Using the generic method 'ConsoleApplication16.Extensions.Parameter<TReg,T>(TReg, string, T)' requires 2 type arguments
Which is just as bad.
I can easily restructure the classes, or even make the methods non-extension-methods by introducing them into the hierarchy, but my question is if I can avoid having to duplicate the methods for the two descendants, and in some way declare them only once, for the base class.
Let me rephrase that. Is there a way to change the classes in the first code example above, so that the syntax in the Main-method can be kept, without duplicating the methods in question?
The code will have to be compatible with both C# 3.0 and 4.0.
Edit: The reason I'd rather not leave both generic type arguments to inference is that for some services, I want to specify a parameter value for a constructor parameter that is of one type, but pass in a value that is a descendant. For the moment, matching of specified argument values and the correct constructor to call is done using both the name and the type of the argument.
Let me give an example:
ServiceContainerBuilder.Register<ISomeService>(r => r
.From(f => f.ConcreteType<FileService>(ct => ct
.Parameter<Stream>("source", new FileStream(...)))));
^--+---^ ^---+----^
| |
| +- has to be a descendant of Stream
|
+- has to match constructor of FileService
If I leave both to type inference, the parameter type will be FileStream, not Stream.
I wanted to create an extension method that could enumerate over a list of things, and return a list of those things that were of a certain type. It would look like this:
listOfFruits.ThatAre<Banana>().Where(banana => banana.Peel != Color.Black) ...
Sadly, this is not possible. The proposed signature for this extension method would have looked like:
public static IEnumerable<TResult> ThatAre<TSource, TResult>
(this IEnumerable<TSource> source) where TResult : TSource
... and the call to ThatAre<> fails because both type arguments need to be specified, even though TSource may be inferred from the usage.
Following the advice in other answers, I created two functions: one which captures the source, and another which allows callers to express the result:
public static ThatAreWrapper<TSource> That<TSource>
(this IEnumerable<TSource> source)
{
return new ThatAreWrapper<TSource>(source);
}
public class ThatAreWrapper<TSource>
{
private readonly IEnumerable<TSource> SourceCollection;
public ThatAreWrapper(IEnumerable<TSource> source)
{
SourceCollection = source;
}
public IEnumerable<TResult> Are<TResult>() where TResult : TSource
{
foreach (var sourceItem in SourceCollection)
if (sourceItem is TResult) yield return (TResult)sourceItem;
}
}
}
This results in the following calling code:
listOfFruits.That().Are<Banana>().Where(banana => banana.Peel != Color.Black) ...
... which isn't bad.
Notice that because of the generic type constraints, the following code:
listOfFruits.That().Are<Truck>().Where(truck => truck.Horn.IsBroken) ...
will fail to compile at the Are() step, since Trucks are not Fruits. This beats the provided .OfType<> function:
listOfFruits.OfType<Truck>().Where(truck => truck.Horn.IsBroken) ...
This compiles, but always yields zero results and indeed doesn't make any sense to try. It's much nicer to let the compiler help you spot these things.
If you have only two specific types of registration (which seems to be the case in your question), you could simply implement two extension methods:
public static DelegateRegistration Parameter<T>(
this DelegateRegistration p, string name, T value);
public static ConcreteTypeRegistration Parameter<T>(
this ConcreteTypeRegistration p, string name, T value);
Then you wouldn't need to specify the type argument, so the type inference would work in the example you mentioned. Note that you can implement both of the extension methods just by delegation to a single generic extension method with two type parameters (the one in your question).
In general, C# doesn't support anything like o.Foo<int, ?>(..) to infer only the second type parameter (it would be nice feature - F# has it and it's quite useful :-)). You could probably implement a workaround that would allow you to write this (basically, by separating the call into two method calls, to get two places where the type inferrence can be applied):
FooTrick<int>().Apply(); // where Apply is a generic method
Here is a pseudo-code to demonstrate the structure:
// in the original object
FooImmediateWrapper<T> FooTrick<T>() {
return new FooImmediateWrapper<T> { InvokeOn = this; }
}
// in the FooImmediateWrapper<T> class
(...) Apply<R>(arguments) {
this.InvokeOn.Foo<T, R>(arguments);
}
Why don't you specify zero type parameters? Both can be inferred in your sample. If this is not an acceptable solution for you, I'm frequently encountering this problem too and there's no easy way to solve the problem "infer only one type parameter". So I'll go with the duplicate methods.
What about the following:
Use the definition you provide:
public static TReg Parameter<TReg, T>(
this TReg p, string name, T value)
where TReg : ParameterizedRegistrationBase
Then cast the parameter so the inference engine gets the right type:
ServiceContainerBuilder.Register<ISomeService>(r => r
.From(f => f.ConcreteType<FileService>(ct => ct
.Parameter("source", (Stream)new FileStream(...)))));
I think you need to split the two type parameters between two different expressions; make the explicit one be part of the type of a parameter to the extension method, so inference can then pick it up.
Suppose you declared a wrapper class:
public class TypedValue<TValue>
{
public TypedValue(TValue value)
{
Value = value;
}
public TValue Value { get; private set; }
}
Then your extension method as:
public static class Extensions
{
public static TReg Parameter<TValue, TReg>(
this TReg p, string name, TypedValue<TValue> value)
where TReg : ParameterizedRegistrationBase
{
// can get at value.Value
return p;
}
}
Plus a simpler overload (the above could in fact call this one):
public static class Extensions
{
public static TReg Parameter<TValue, TReg>(
this TReg p, string name, TValue value)
where TReg : ParameterizedRegistrationBase
{
return p;
}
}
Now in the simple case where you are happy to infer the parameter value type:
ct.Parameter("name", "Lasse")
But in the case where you need to explicitly state the type, you can do so:
ct.Parameter("list", new TypedValue<IEnumerable<int>>(new List<int>()))
Looks ugly, but hopefully rarer than the simple fully-inferred kind.
Note that you could just have the no-wrapper overload and write:
ct.Parameter("list", (IEnumerable<int>)(new List<int>()))
But that of course has the disadvantage of failing at runtime if you get something wrong. Unfortunately away from my C# compiler right now, so apologies if this is way off.
I would used the solution:
public class JsonDictionary
{
public static readonly Key<int> Foo = new Key<int> { Name = "FOO" };
public static readonly Key<string> Bar = new Key<string> { Name = "BAR" };
IDictionary<string, object> _data;
public JsonDictionary()
{
_data = new Dictionary<string, object>();
}
public void Set<T>(Key<T> key, T obj)
{
_data[key.Name] = obj;
}
public T Get<T>(Key<T> key)
{
return (T)_data[key.Name];
}
public class Key<T>
{
public string Name { get; init; }
}
}
See:
C#: Exposing type safe API over heterogeneous dictionary