How can I type safely load code from multiple sources that deal with an unknown type?
I need to be able to, at runtime, load two classes that share an unknown type, like this:
interface IProducer<out A>
{
public A CookOne();
}
interface IConsumer<in A>
{
public void EatOne(A food);
}
<edit>
Here are two example classes
class IntChef : IProducer<int>
{
private int _counter = 0;
public int CookOne()
{
return counter++;
}
}
开发者_如何学JAVAclass IntCustomer : IConsumer<int>
{
public void EatOne(int food)
{
Console.WriteLine("I ate a {0}", food);
}
}
The goal is to load an implementation of each interface, sharing the type they communicate via, and create a new object that doesn't care how the two loaded types communicate.
</edit>
The entire list of possible involved types can't be known at compile time because they don't exist yet. The software that uses these types is something like this:
interface IStrategyFactory<A>
{
public IStrategy MakeAStrategy(IProducer<A> producer, IConsumer<A> consumer);
}
interface IStrategy
{
public void DoSomething();;
}
How can I load external binary code (from two different sources) and pass them to the factory (or wherever else) in a type-safe manner, so that I can't, for example, pass in a IProducer and an IConsumer?
The best resource I can find on this so far is http://codebetter.com/blogs/glenn.block/archive/2009/08/20/open-generic-support-in-mef.aspx
Optimally the program itself would have types like this:
interface IStrategyFactory<A>
{
public IStrategy MakeAStrategy(IProducer<A> producer, IConsumer<A> consumer);
}
interface IStrategy
{
public void DoSomething();;
}
You can use reflection to create new objects at runtime, even generic classes. You can create a class factory that loads them based on a configuration file that lists out the types. It sounds like you're basically looking for an IOC container. That's basically what the Windsor-Castle project does, with the addition of a nice interface. That may not fit your exact needs, but there's many other open-source projects out there that may work for you.
I would also suggest you use an interface to define the methods you want to use in your CookOne and EatOne methods, and to add a generic constraint to the IProducer and IConsumer interfaces.
interface ISomethingOrOther{}
interface IProducer<out A> where A : ISomethingOrOther
{
public A CookOne();
}
interface IConsumer<in A> where A : ISomethingOrOther
{
public void EatOne(A food);
}
精彩评论