问题
I am trying to implement Factory Pattern with MEF.
Here is my solution
Core Project
IClass
ObjectFactory static Class(This is where the problem is)
Project A
[Export(typeof(IClass))]
[ExportMetadata("Type", "TypeA")]
public classA : IClass
{}
ProjectB
[Export(typeof(IClass))]
[ExportMetadata("Type", "TypeB")]
public classB : IClass
{}
I am facing problem when I am trying to create object dynamically
And here is factory class:
public static class ObjectFactory
{
private static readonly CompositionContainer _container;
[ImportMany]
public static IEnumerable<Lazy<IClass, IMetaData>> objectTypes;
static ObjectFactory()
{
AggregateCatalog catalog = new AggregateCatalog();
catalog.Catalogs.Add(new DirectoryCatalog(Environment.CurrentDirectory));
_container = new CompositionContainer(catalog);
try
{
objectTypes = _container.GetExports<IClass, IMetaData>();
}
catch (CompositionException compositionException)
{
Console.WriteLine(compositionException.ToString());
Console.ReadLine();
}
}
public static IClass CreateObject(ObectType objectType)
{
IClass outProvider;
Type typeToLoad = objectTypes.Where(x => x.Metadata.Type == objectType.ToString()).FirstOrDefault().GetType();
outProvider = (IClass)Activator.CreateInstance(typeToLoad);
return outProvider;
}
}
回答1:
If you want a new "NonShared" instance provided on every call to CreateObject then I suggest this refactoring.
private static readonly CompositionContainer _container;
static ObjectFactory()
{
var directoryCatalog = new DirectoryCatalog(Environment.CurrentDirectory)
_container = new CompositionContainer(directoryCatalog);
}
public static IClass CreateObject(ObectType objectType)
{
var objectTypes objectTypes = new List<Lazy<IClass, IMetaData>>();
try
{
objectTypes.AddRange(_container.GetExports<IClass, IMetaData>());
}
catch (CompositionException compositionException)
{
Console.WriteLine(compositionException.ToString());
Console.ReadLine();
}
return objectTypes.FirstOrDefault(x => x.Metadata.Type == objectType.ToString());
}
You see MEF will resolve new instances (non shared ones that is) every time it composes types or you you call GetExports (and all other overload of this function). Alternatively you can export IClass factories instead, then you will have a collection of there providers.
P.S. [ImportMany] on objectTypes member in your example is superfluous, since you are not composing this type (I don't believe you even can since its static), you are simply setting it programmatically from the output of GetExports
回答2:
I could fix the issue
public static IClass CreateObject(ObectType objectType)
{
return objectTypes.Where(x => x.Metadata.Type == objectType.ToString()).FirstOrDefault().Value;
}
回答3:
You can try below solution
//Project A
[PartCreationPolicy(CreationPolicy.NonShared)]
[Export("TypeA", typeof(IClass))]
public classA : IClass
{}
//Project B
[PartCreationPolicy(CreationPolicy.NonShared)]
[Export("TypeB", typeof(IClass))]
public classB : IClass
{}
// Your class with new Create Object Method using generics
public static class ObjectFactory
{
private static readonly CompositionContainer _container;
[ImportMany]
public static IEnumerable<Lazy<IClass, IMetaData>> objectTypes;
static ObjectFactory()
{
AggregateCatalog catalog = new AggregateCatalog();
catalog.Catalogs.Add(new DirectoryCatalog(Environment.CurrentDirectory));
_container = new CompositionContainer(catalog);
}
//get object method
public static T CreateObject<T>(string objectType)
{
try
{
return _container?.GetExportedValueOrDefault<T>(objectType);
}
catch (Exception)
{
}
return null;
}
}
// Class To create Objects
public class classToConsume
{
public void CreateMEFInstances()
{
IClass objClassA = ObjectFactory.CreateObject<IClass>("TypeA");
IClass objClassB = ObjectFactory.CreateObject<IClass>("TypeB");
}
}
来源:https://stackoverflow.com/questions/26292563/factory-pattern-with-managed-ext-framework-mef