Reputation: 201
Consider the following situation:
[Export]
class A { }
class B
{
[Import]
private A a;
}
// Instantiates class B.
class C
{
public C(Type type){ /*Instantiate Class B here.*/}
public void PerfomOperationUsingClassB() { }
}
class D
{
void Initialize()
{
var catalog = new AssemblyCatalog(Assembly.GetAssembly(typeof(A)));
var container = new CompositionContainer(catalog);
// Is there any way to compose A with B?
C c = new C(typeof(B));
c.PerfomOperationUsingClassB();
}
}
Problem: I have an access to class "A" and "B" but class "C" is located in the assembly that I can't modify (thus can't modify the class "C"). Is there any way to compose "A" and "B"?
Upvotes: 1
Views: 1629
Reputation: 674
You could use the ServiceLocator in class B
like this
class B
{
private A a;
B()
{
a = Microsoft.Practices.ServiceLocator.Current.GetInstance<A>();
}
}
Upvotes: 0
Reputation: 3014
I don't think so, not without a reference to the instance of B...
If you had the reference you could call:
container.SatisfyImportsOnce(instanceOfB);
Upvotes: 1
Reputation: 61589
Unfortunately, without access to whatever the constructor of C
is doing, you pretty much out of luck. The constructor of C
seems to want to initialise an instance of B
using the type itself... does it provide any mechanism of intercepting the initialisation of B
within C
?
If C
were to accept an instance of B
instead, you could easily just pass in a composed instance of B
into the constructor. If you wanted to export the closed type, C
, you could do something like:
public class MefAdapter<T, TExport>
{
private readonly Func<T, TExport> _factory = CreateFactory();
private readonly T _arg;
[ImportingConstructor]
public MefAdapter(T arg)
{
_arg = arg;
}
[Export]
public TExport Export
{
get { return _factory(_arg); }
}
internal static Func<T, TExport> CreateFactory()
{
var tArg = typeof(T);
var tExport = typeof(TExport);
var arg = Expression.Parameter(tArg, "arg");
var ctor = tExport.GetConstructor(new[] { tArg });
var ctorExp = Expression.New(ctor, arg);
return Expression.Lamda<Func<T, TExport>>(ctorExp, arg).Compile();
}
}
(This is based on Mark Seemann's Resolving closed types article).
With that, should C
actually look like:
public class C
{
public C(B b)
{
}
}
You could have that closed type satisfied by an automatic creation of B
:
var typeCatalog = new TypeCatalog(typeof(MefAdapter<C>));
var catalog = new AggregateCatalog(new DirectoryCatalog("."), typeCatalog);
var container = new CompositionContainer(catalog);
var c = container.ComposeExportedValue<C>();
// This instance of C should have a composed instance of B injected.
Upvotes: 1