Satisfying imports for an existing object using MEF - c#

Given an arbitrary already existing object which is attributed with [Import] tags, what's the tambourine dance I have to do in order to get MEF to fill in the imports?
Much of the blog documentation seems to be built against preview versions of MEF and don't work anymore - I'm using the released one that's part of .NET 4.0 (or alternatively, MEF 2.0 Preview 3).
AggregateCatalog _catalog;
CompositionContainer _container;
public void Composify(object existingObjectWithImportTags)
{
lock(_container) {
var batch = new CompositionBatch();
// What do I do now?!?!
}
}

MEF resolves Imports (through property or constructor injection), along whith their own dependencies, from exported types in the registered assemblies registered in the catalog (including the current assembly).
If you want to create an object directly (using the new keyword), or in case the export wasn't ready at the time of the creation, you can use the container to satisfy the imports of an object, using:
_container.SatisfyImportsOnce(yourObject);
I've put together a little scenario doing just that. here's the code:
public class Demo
{
private readonly CompositionContainer _container;
[Import]
public IInterface Dependency { get; set; }
public Demo(CompositionContainer container)
{
_container = container;
}
public void Test()
{
//no exported value, so the next line would cause an excaption
//var value=_container.GetExportedValue<IInterface>();
var myClass = new MyClass(_container);
//exporting the needed dependency
myClass.Export();
_container.SatisfyImportsOnce(this);
//now you can retrieve the type safely since it's been "exported"
var newValue = _container.GetExportedValue<IInterface>();
}
}
public interface IInterface
{
string Name { get; set; }
}
[Export(typeof(IInterface))]
public class MyClass:IInterface
{
private readonly CompositionContainer _container;
public MyClass()
{
}
public MyClass(CompositionContainer container)
{
_container = container;
}
#region Implementation of IInterface
public string Name { get; set; }
public void Export()
{
_container.ComposeExportedValue<IInterface>(new MyClass());
}
#endregion
}
Now, just use new Tests(new CompositionContainer()).Test(); to start the demo.
Hope this helps :)

_container.ComposeParts(existingObjectWithImportTags);
ComposeParts is an extension method that you are looking for.
It simply creates a CompositionBatch and calls AddPart(AttributedModelServices.CreatePart(attributedObject)) and then calls _container.Compose(batch).

Related

HOW TO: Tell a Module Which Region the View to Register to at Runtime

Is it possible to pass on the region name to the module so it knows which region the view should register with?
I see in many code example that the regionName is hardcoded in the module initialize method.
What I want to do is have the SHELL pass in the region name when the module is registering the view to a region.
If this is not possible or not recommended, why would this be a bad or good thing?
Your best bet would be to create a service that manages your region names and inject that into the modules.
IRegionNameService
{
string MainRegion {get;}
string DetailRegion {get;}
}
Register your service as a singleton with your container, and now you can have it configured just the way you want it when the app launches and before the modules are loaded.
How I, and others, handle the idea of avoiding magic strings being set/passed all over the place, is to centralize the storage of the strings, so you can refer to them on other places.
First, you need a class that will store the string(s). I use one called RegionNames for my Prism... region... names. An Example is below.
namespace Application.Shared
{
public class RegionNames
{
// Main window regions
public static string RibbonRegion { get { return "RibbonRegion"; } }
public static string TitleBarRegion { get { return "TitleBarRegion"; } }
public static string ToolBarRegion { get { return "ToolBarRegion"; } }
public static string DashboardRegion { get { return "DashboardRegion"; } }
public static string ContentRegion { get { return "ContentRegion"; } }
}
}
Once you have this established in a central location in your solution, like an assembly that all the other assemblies can reference, you can use it like below.
using Application.Shared;
namespace Application.Modules
{
public class ModuleX : IModule
{
private readonly IUnityContainer _container;
private readonly IRegionManager _region_manager;
public ModuleX (IUnityContainer container, IRegionManager region_manager)
{
_container = container;
_region_manager = region_manager;
}
public override void Initialize()
{
_region_manager.RegisterViewWithRegion(RegionNames.RibbonRegion, typeof(ToolViewX));
_region_manager.RegisterViewWithRegion(RegionNames.ContentRegion, typeof(FinderViewX));
}
}
}
As long as a class can access the namespace that RegionNames class uses, they can access the static properties. Nothing to pass this way.
This technique isn't limited to Prism, or C#! You can use this pattern in any programming language. Instead of calling RegionNames, call it StringBag, or whatever!
Hope this helps you.

Compose Imports using run-time defined Contract Name

I have an MEF Export like below:
public interface IMyInterface { }
public interface IInterfaceData
{
string[] Data { get; }
}
[Export("MyContractName", typeof(IMyInterface))]
[ExportMetadata("Data", "SomeData", IsMultiple = true)]
public class MyInterfaceClass : IMyInterface { }
Which I then Import using:
public class MyClass {
[ImportMany("MyContractName", typeof(IMyInterface))]
private IEnumerable<Lazy<IMyInterface, IInterfaceData>> _operations;
private CompositionContainer _container;
private void Compose() {
var catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
_container = new CompositionContainer(catalog);
_container.ComposeParts(this);
}
}
This works fine. However, I would like to be able to Compose my Imports at Run Time using a contract name based on the currently executing business logic. In other words, I would like to be able import a variable contract name. I can get around this by doing this:
private void Compose() {
var contractName = "MyContractName"; // note this would be determined at run-time
var catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
_container = new CompositionContainer(catalog);
var foundExports = _container.GetExports<IMyInterface, IInterfaceData>(contractName);
_operations = foundExports; // set manually
}
I am more than happy to do to this*. However, there is now no reason for the [ImportMany] attribute and I can no longer use ComposeParts(). I would like to keep things consistent throughout my project (for my sake, and my team's) and would like to be able to rely on MEF Attributes, Compose()/ComposeParts() or both.
Is there some other way to define the Import attributes, such that calling _container.Compose() would take into account a run-time defined contract name? Perhaps the Exports need to be changed or there is something else in the MEF framework that is available to me (attribute wise)?
*I am not sure if this is even "correct". even though it does work. It just feels sloppy if I'm trying to keep all things somewhat consistent.
This can be done by directly using a CompositionBatch on your container.
var batch = new CompositionBatch();
// Add the export to the batch via method or object referebce
batch.AddExport(new Export(name, partFactory));
batch.AddExport(new Export(part.Name, () => part));
// Compose into your CompositionContainer
_container.Compose(batch);
private MyClass PartFactory()
{
// TODO: create the part to export..
}
Note that for the container object, it is possible to export the container itself using CompositionOptions.ExportCompositionService during construction, thus allowing
[Import] CompositionContainer _container;

How to create new objects from MEF imports

I am a little confused by MEF, I thought I had begun to understand it but it appears I am not quite there.
So, I have a list of test steps in XML that I want to read in. The idea is that the main application doesn't know anything about the types at run time.
<TestSteps>
<TestRunner xsi:type="SimulateDc" Measurement="54"/>
<TestRunner xsi:type="MeasureDc" Output="1"/>
</TestSteps>
So I have a base type with a static "results" class that allows me to save information to pass between steps (The Output attribute in the XML above). The test handlers here are exported by MEF, I read them in at runtime and then get the Type to pass into the XML serializer to create a list of handlers. This all works and I get a list of test runners. I have a DataTemplate export for each type here so when I use a Content Control it knows how to draw itself. All all seems fine, however I think I have gone wrong in my thought process.
One issue is that I now want to tie the imported handlers to some hardware. the hardware handling routines are intended to be handled by yet more MEF imports
So with an interface like this:
public interface IMeasureHW
{
double Measure();
}
Then using this:
[Export("MeasureDc", typeof(IMeasureHW))]
public class MeasureDcHW : IMeasureHW
{
public double Measure()
{
return 54.0;
}
}
Then in one of my test handlers I have done this:
[Import("MeasureDc", typeof(IMeasureHW))]
IMeasureHW hardware { get; set; }
My importing is carried out like this:
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
var catalog = new AggregateCatalog();
catalog.Catalogs.Add(new DirectoryCatalog("."));
catalog.Catalogs.Add(new AssemblyCatalog(Assembly.GetExecutingAssembly()));
_container = new CompositionContainer(catalog);
_container.ComposeParts(this);
MainWindow.Show();
}
However, I am guessing the XML serialization above and using the Type information as I do would definitely mean the import would be null so implying my thought patterns for the design are in error.
I did manage to get it to work by exporting the CompositionContainer and then after loading the XML I am able to do this:
foreach (TestRunnerBase t in testSteps)
{
_container.SatisfyImportsOnce(t);
}
But that feels a bit wrong to me, as the initial list of imported test steps isn't being used for anything apart from getting the type. So I was thinking that I should be exporting the data as MEF parts and then independently exporting the handlers, then somehow when I read in my list of data from the XML I ask for a handler from the list? If that makes sense?
I couldn't work out how you would tie them together in this way as the MEF composition is all handled in my App.xaml.cs and the test steps are in a view model elsewhere. I was thinking something along the lines of using metadata to tie data to a handler, and then finding the corresponding handler in the imported list. Perhaps I should carry out an initial parse to build a dictionary to speed up lookups?
Is this more the way it should be done? Any help appreciated, I am already quite light in the hair department so I can't afford to lose more
Please correct me if I'm wrong - It seems as though you could achieve your goal by chaining imports: innermost being your TestRunner collection, then the hardware classes, then finally the content control.
In the example below these are Class2 : MySubInterface, Class1 : MyInterface, and Program respectively:
/////inner
using MyHostingNamespace;
namespace ClassLibrary1
{
[Export("class2", typeof(MySubInterface))]
class Class2 : MySubInterface
{
public string MyProperty { get; set; }
public Class2()
{
MyProperty = "Class2";
}
}
}
////middle
using MyHostingNamespace;
namespace ClassLibrary1
{
[Export("class1", typeof(MyInterface))]
public class Class1 : MyInterface
{
[Import("class2", AllowDefault=true)]
MySubInterface myClass2;
public string MyProperty {get;set;}
public Class1()
{
AggregateCatalog catalog = new AggregateCatalog();
catalog.Catalogs.Add(new AssemblyCatalog(Assembly.GetExecutingAssembly()));
CompositionContainer _container = new CompositionContainer(catalog);
_container.ComposeParts(this);
MyProperty = myClass2.MyProperty;
}
}
}
////outer
namespace MyHostingNamespace
{
class Program
{
[Import("class1")]
public MyInterface class1;
public Program()
{
AggregateCatalog catalog = new AggregateCatalog();
catalog.Catalogs.Add(new AssemblyCatalog(Assembly.GetExecutingAssembly()));
catalog.Catalogs.Add(new DirectoryCatalog("."));
CompositionContainer _container = new CompositionContainer(catalog);
_container.ComposeParts(this);
}
static void Main(string[] args)
{
Program p = new Program();
Console.WriteLine(p.class1.MyProperty);
}
}
public interface MyInterface
{
string MyProperty { get; set; }
}
public interface MySubInterface
{
string MyProperty { get; set; }
}
}

How can I handle recursive composition in MEF?

Consider the following code sample that uses MEF to create an object of type Importer that imports an object of type ImporterExporter which in turn imports an object of type Exporter, i.e. Importer -> ImporterExporter -> Exporter. The catalog is managed by a CompositionUtility (obviously simplified for this example).
I know that MEF will resolve imports recursively on imported parts. However, because I want to have the option to instantiate each of these classes independetly, every class with imports also composes itself in its constructor to resolve those imports.
using System;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.Reflection;
namespace MefRecursionSample
{
class Program
{
static void Main(string[] args)
{
// var importerExporter = new ImporterExporter(); // include this and composition will work
var importer = new Importer();
Console.Write(importer.ImporterExporter.Exporter.Value); // should print 7
Console.ReadKey();
}
}
class CompositionUtility
{
static CompositionUtility()
{
var executingAssembly = Assembly.GetExecutingAssembly();
var assemblyCatalog = new AssemblyCatalog(executingAssembly);
_compositionContainer = new CompositionContainer(assemblyCatalog);
}
private static CompositionContainer _compositionContainer;
private static bool _isComposing;
public static void Compose(object part)
{
_compositionContainer.ComposeParts(part);
}
}
class Importer
{
public Importer()
{
CompositionUtility.Compose(this);
}
[Import]
public ImporterExporter ImporterExporter { get; set; }
}
[Export]
class ImporterExporter
{
public ImporterExporter()
{
CompositionUtility.Compose(this);
}
[Import]
public Exporter Exporter { get; set; }
}
[Export]
class Exporter
{
public int Value { get { return 7; } }
}
}
Running the code as is leads to a composition error "The ComposablePart of type MefRecursionSample.Importer' cannot be recomposed....", obviously because I am trying to explictly compose something that MEF also wants to compose.
What surprised me, was the fact that when I included the first line of the Main method, i.e. create an object of type ImporterExporter without MEF, this "double-composition" no longer caused an exception. Why is that?
Also, how could I make it work such that I could instantiate each of these indepennetly, yet also make them compose themselves when chained as in the sample. I figured I would introduce a boolean flag _compositionInProgress on the CompositionUtility and immediately return from Compose() when the flag is set to avoid the recursive composition. Is there a better way?
The flag I considered setting in the CompositionUtility's Compose method does not work, because there can be cases where the string of automatic imports is interrupted. For instance, in the question's example if Exporter instantiated a class in its constructor using new and this class would want to compose itself. Under the original solution, that class' call to Ccompose would return immediately, leaving the class uncomposed.
Because I want classes to compose themselves (thus making it unneccessary for their users to even know about MEF), the only solution was to establish the rule that classes with an [Export] attribute must not call Compose(this). Because they will be composed automatically by MEF when being imported, this would result in "double composition" and thus throw an exception.
If it is a requirement that classes marked with [Export] have to instantiated independently via new instead of nly imported via MEF, they have to have an addional constructor with a boolean flag which when set well trigger composition of that class. The default behavior, however, has to be no composition in order to avoid the aforementioned "double composition".
why not simply do this?
class Program
{
private static CompositionContainer _compositionContainer;
static void Main(string[] args)
{
//compose the container just one time in your app
var assemblyCatalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
_compositionContainer = new CompositionContainer(assemblyCatalog);
var importer = _compositionContainer.GetExportedValue<Importer>();
Console.Write(importer.ImporterExporter.Exporter.Value); // should print 7
Console.ReadKey();
}
}
[Export]
class Importer
{
[ImportingConstructor]
public Importer(ImporterExporter imex)
{
this.ImporterExporter = imex;
}
public ImporterExporter ImporterExporter { get; private set; }
}
[Export]
class ImporterExporter
{
[ImportingConstructor]
public ImporterExporter(Exporter exporter)
{
this.Exporter = exporter;
}
public Exporter Exporter { get; private set; }
}
[Export]
class Exporter
{
public int Value { get { return 7; } }
}
What you really want to do (I think) is calling container.SatisfyImportsOnce() on an object and not ComposeParts .
ComposeParts adds all exports tree to the catalog while SatisfyImportsOnce each object is to itself , composing parts and thats it , no registeration of recursive exports , so you can call constructor or use importing constructor , you can have both.
James.

Fake ASMX Web Service Call

I built a .NET ASMX web service connecting to an SQL Server database. There is a web service call GetAllQuestions().
var myService = new SATService();
var serviceQuestions = myService.GetAllQuestions();
I saved the result of GetAllQuestions to GetAllQuestions.xml in the local application folder
Is there any way to fake the web service call and use the local xml result?
I just want to take the contents of my entire sql table and have the array of objects with correlating property names automatically generated for me just like with LINQ to SQL web services.
Please keep in mind that I am building a standalone Monotouch iPhone application.
Use dependency injection.
//GetSATService returns the fake service during testing
var myService = GetSATService();
var serviceQuestions = myService.GetAllQuestions();
Or, preferably, in the constructor for the object set the SATService field (so the constructor requires the SATService to be set. If you do this, it will be easier to test.
Edit: Sorry, I'll elaborate here. What you have in your code above is a coupled dependency, where your code creates the object it is using. Dependency injection or the Inversion of Control(IOC) pattern, would have you uncouple that dependency. (Or simply, don't call "new" - let something else do that - something you can control outside the consumer.)
There are several ways to do this, and they are shown in the code below (comments explain):
class Program
{
static void Main(string[] args)
{
//ACTUAL usage
//Setting up the interface injection
IInjectableFactory.StaticInjectable = new ConcreteInjectable(1);
//Injecting via the constructor
EverythingsInjected injected =
new EverythingsInjected(new ConcreteInjectable(100));
//Injecting via the property
injected.PropertyInjected = new ConcreteInjectable(1000);
//using the injected items
injected.PrintInjectables();
Console.WriteLine();
//FOR TESTING (normally done in a unit testing framework)
IInjectableFactory.StaticInjectable = new TestInjectable();
EverythingsInjected testInjected =
new EverythingsInjected(new TestInjectable());
testInjected.PropertyInjected = new TestInjectable();
//this would be an assert of some kind
testInjected.PrintInjectables();
Console.Read();
}
//the inteface you want to represent the decoupled class
public interface IInjectable { void DoSomething(string myStr); }
//the "real" injectable
public class ConcreteInjectable : IInjectable
{
private int _myId;
public ConcreteInjectable(int myId) { _myId = myId; }
public void DoSomething(string myStr)
{
Console.WriteLine("Id:{0} Data:{1}", _myId, myStr);
}
}
//the place to get the IInjectable (not in consuming class)
public static class IInjectableFactory
{
public static IInjectable StaticInjectable { get; set; }
}
//the consuming class - with three types of injection used
public class EverythingsInjected
{
private IInjectable _interfaceInjected;
private IInjectable _constructorInjected;
private IInjectable _propertyInjected;
//property allows the setting of a different injectable
public IInjectable PropertyInjected
{
get { return _propertyInjected; }
set { _propertyInjected = value; }
}
//constructor requires the loosely coupled injectable
public EverythingsInjected(IInjectable constructorInjected)
{
//have to set the default with property injected
_propertyInjected = GetIInjectable();
//retain the constructor injected injectable
_constructorInjected = constructorInjected;
//using basic interface injection
_interfaceInjected = GetIInjectable();
}
//retrieves the loosely coupled injectable
private IInjectable GetIInjectable()
{
return IInjectableFactory.StaticInjectable;
}
//method that consumes the injectables
public void PrintInjectables()
{
_interfaceInjected.DoSomething("Interface Injected");
_constructorInjected.DoSomething("Constructor Injected");
_propertyInjected.DoSomething("PropertyInjected");
}
}
//the "fake" injectable
public class TestInjectable : IInjectable
{
public void DoSomething(string myStr)
{
Console.WriteLine("Id:{0} Data:{1}", -10000, myStr + " For TEST");
}
}
The above is a complete console program that you can run and play with to see how this works. I tried to keep it simple, but feel free to ask me any questions you have.
Second Edit:
From the comments, it became clear that this was an operational need, not a testing need, so in effect it was a cache. Here is some code that will work for the intended purpose. Again, the below code is a full working console program.
class Program
{
static void Main(string[] args)
{
ServiceFactory factory = new ServiceFactory(false);
//first call hits the webservice
GetServiceQuestions(factory);
//hists the cache next time
GetServiceQuestions(factory);
//can refresh on demand
factory.ResetCache = true;
GetServiceQuestions(factory);
Console.Read();
}
//where the call to the "service" happens
private static List<Question> GetServiceQuestions(ServiceFactory factory)
{
var myFirstService = factory.GetSATService();
var firstServiceQuestions = myFirstService.GetAllQuestions();
foreach (Question question in firstServiceQuestions)
{
Console.WriteLine(question.Text);
}
return firstServiceQuestions;
}
}
//this stands in place of your xml file
public static class DataStore
{
public static List<Question> Questions;
}
//a simple question
public struct Question
{
private string _text;
public string Text { get { return _text; } }
public Question(string text)
{
_text = text;
}
}
//the contract for the real and fake "service"
public interface ISATService
{
List<Question> GetAllQuestions();
}
//hits the webservice and refreshes the store
public class ServiceWrapper : ISATService
{
public List<Question> GetAllQuestions()
{
Console.WriteLine("From WebService");
//this would be your webservice call
DataStore.Questions = new List<Question>()
{
new Question("How do you do?"),
new Question("How is the weather?")
};
//always return from your local datastore
return DataStore.Questions;
}
}
//accesses the data store for the questions
public class FakeService : ISATService
{
public List<Question> GetAllQuestions()
{
Console.WriteLine("From Fake Service (cache):");
return DataStore.Questions;
}
}
//The object that decides on using the cache or not
public class ServiceFactory
{
public bool ResetCache{ get; set;}
public ServiceFactory(bool resetCache)
{
ResetCache = resetCache;
}
public ISATService GetSATService()
{
if (DataStore.Questions == null || ResetCache)
return new ServiceWrapper();
else
return new FakeService();
}
}
Hope this helps. Good luck!
when you say fake the call, are you just testing the client side?
you could use fiddler, intercept the request and return the local xml file to the client. No messing around with your client code then.
To elaborate on Audie's answer
Using DI would get you what you want. Very simply you would create an interface that your real object and your mock object both implement
public interface IFoo
{}
Then you would have your GetSATService method return either a MockSATSerivce or the real SATService object based on your needs.
This is where you would use a DI container (some object that stores interface to concrete type mappings) You would bootstrap the container with the types you want. So, for a unit test, you could contrstruct a mock container that registers the MockSATService as the implementer of the IFoo interface.
Then you would as the container for the concrete type but interface
IFoo mySATService = Container.Resolve<IFoo>();
Then at runtime you would just change out the container so that it bootstraps with the runtime types instead of the mock types but you code would stay the same (Because you are treating everything as IFoo instead SATService)
Does that make sense?
Over time I found that an interesting way to do this is by extracting an interface and creating a wrapper class. This adapts well to a IoC container and also works fine without one.
When testing, create the class passing a fake service. When using it normally, just call the empty constructor, which might simply construct a provider or resolve one using a config file.
public DataService : IDataService
{
private IDataService _provider;
public DataService()
{
_provider = new RealService();
}
public DataService(IDataService provider)
{
_provider = provider;
}
public object GetAllQuestions()
{
return _provider.GetAllQuestions();
}
}

Categories