Reputation: 23264
public interface IProcessor<T>
{
void Process(T instance);
}
foreach(AbstractType instance in myClass.SomeCollection)
OnProcess(instance);
public void OnProcess<T>(T instance)
{
IProcessor<T> processor =
unityContainer.Resolve<IProcessor<T>>();
processor.Process(instance);
}
The problem with this code is that the in
OnProcess
is always AbstractType
, and not the concrete type of the instance being passed. I currently see two possibilities.
01: Create a non generic IProcessor
and use it as the base for IProcessor
. Any implementor will have to implement both generic and non-generic Process
methods, typically typecasting and passing onto the generic method.
02: Use Type.MakeGenericType
to get the IProcessor
, resolve that, and then use reflection to invoke the Process method.
Both of these approaches feel a bit "unclean". Can anyone think of a way I can do this without having to resort to these practices?
Thanks
Pete
Upvotes: 1
Views: 1273
Reputation: 1064104
2 will be a performance killer (the necessary dynamic/relection invoke in particular is slow)
1 is a common answer to this problem, especially with explicit implementation; the problem is getting hold of the type... does unity allow query with a Type
instance, rather than via generics? If so something like below... of course, you might still have to use MakeGenericType
:
Type intType = typeof(IProcessor<>).MakeGenericType(instanceType);
IProcessor proc = (IProcessor) IoC.Resolve(intType);
Where instanceType
is perhaps via instance.GetType()
. For similar reasons, it might be helpful to expose the T
as a Type
on the IProcessor
:
public interface IProcessor
{
void Process(object instance);
Type InstanceType {get;}
}
public interface IProcessor<T> : IProcessor
{
void Process(T instance);
}
class SomeClass: IProcessor<int>
{
public void Process(int instance)
{
throw new NotImplementedException();
}
Type IProcessor.InstanceType {get {return typeof(int);}}
void IProcessor.Process(object instance)
{
Process((int)instance);
}
}
Of course, an (optional) base-class might allow you to avoid some of this per-implementation:
abstract class SomeBase<T> : IProcessor<T>
{
public void Process(T instance)
{
OnProcess(instance);
}
Type IProcessor.InstanceType {get {return typeof(T);}}
void IProcessor.Process(object instance)
{
Process((T)instance);
}
protected abstract void OnProcess(T instance);
}
Upvotes: 3
Reputation: 3696
If I understand your problem, you want to call a process that's dependent on 2 types (the type of processor, and the object being processed). Is that right? If that's the case, you can use a multi-method pattern for this kind of problem. Here's an example:
public interface IProcessor
{
void Process( IThingToProcess p ); // Will call p.ProcessMe()
void Process( ThingToProcess1 concreteP ); // Called back from ThingToProcess1.ProcessMe
}
public interface IThingToProcess
{
void ProcessMe( IProcessor p );
}
public class ThingToProcess1 : IThingToProcess
{
public void ProcessMe( IProcessor p ) { p.Process( this ); }
}
Upvotes: 0