How to put an interface in a generic dynamically?
I have the following test class:
public class OutsideClass
{
private List<Type> _interfaces = null;
public void InjectInterfaces(Type[] types)
{
if(_interfaces == null)
{
_interfaces = new List<Type>();
}
foreach (var type in types)
{
if(type.IsInterface)
{
_interfaces.Add(type);
}
}
}
public void PerformSomethingWithTheInterfaces()
{
foreach (var i in _interfaces)
{
new Test<i>().PerformSomething(); // On this line the error occurs
}
}
}
internal class Test<T>
{
internal void PerformSomething()
{
}
}
This gives me on however the message Type or namespace name expected
. How can I adjust this code so that it works?
What I am trying to do is to pass in a bunc开发者_运维百科h of interfaces to a class library, there loop over the interfaces and use Unity to Resolve, based on the interface, something. I use the Resolve extension method.
You'd need to use reflection... something like this:
foreach (Type type in _interfaces)
{
Type concreteType = typeof(Test<>).MakeGenericType(new Type[] { type });
MethodInfo method = concreteType.GetMethod("PerformSomething",
BindingFlags.Instance | BindingFlags.NonPublic);
object instance = Activator.CreateInstance(concreteType);
method.Invoke(instance, null);
}
(You may need to make minor changes - the above isn't tested or even compiled.)
With C# 4 and dynamic typing, you can make it somewhat simpler:
foreach (Type type in _interfaces)
{
Type concreteType = typeof(Test<>).MakeGenericType(new Type[] { type });
dynamic d = Activator.CreateInstance(concreteType);
d.PerformSomething();
}
You cannot pass values as generic arguments. Only types. To be clear:
typeof(string) != string.
I don't think this can work. You specialize a generic statically on the type name. You can't pass in a reference to the Type
object.
There are ways to do what you want, but they involve C# 4 and DynamicObject
.
You might really want to look at C# 4's MEF just as an idea as a unity replacement I think it stands up really well myself and simplifies the resolution mechanisms a lot, and may give functionality to complete the task you're attempting more simply..
namespace MEF_Interface
{
// Interface to recognize the concrete implementation as
public interface IMessageWriter
{
void WriteMessage();
}
}
namespace MEF_HelloMessageWriter
{
// Concrete implementation in another assembly
[Export(typeof(IMessageWriter))]
public class HelloMessageWriter : IMessageWriter
{
public void WriteMessage() { Console.WriteLine("Hello!"); }
}
}
namespace MEF_GoodbyeMessageWriter
{
// Concrete implementation in another assembly
[Export(typeof(IMessageWriter))]
public class GoodbyeMessageWriter : IMessageWriter
{
public void WriteMessage() { Console.WriteLine("Goodbye!"); }
}
}
namespace MEF_Example
{
class DIContainer
{
[Import]
public IMessageWriter MessageWriter { get; set; }
public DIContainer(string directory)
{
// No more messy XML DI definition, just a catalog that loads
// all exports in a specified directory. Filtering is also available.
DirectoryCatalog catalog = new DirectoryCatalog(directory);
catalog.Refresh();
var container = new CompositionContainer(catalog);
container.ComposeParts(this);
}
}
class Program
{
static void Main(string[] args)
{
string helloMessageWriterPath =
@"C:\shared\Projects\MEF_Example\MEF_HelloMessageWriter\bin\Debug";
string goodbyeMessageWriterPath =
@"C:\shared\Projects\MEF_Example\MEF_GoodbyeMessageWriter\bin\Debug";
DIContainer diHelloContainer = new DIContainer(helloMessageWriterPath);
diHelloContainer.MessageWriter.WriteMessage();
DIContainer diGoodbyeContainer = new DIContainer(goodbyeMessageWriterPath);
diGoodbyeContainer.MessageWriter.WriteMessage();
Console.ReadLine();
}
}
}
精彩评论