Why SatisfyImportsOnce method doesn't work with the object parameter? - c#

I have been following this MSDN example about the CompositionContainer class (System.ComponentModel.CompositionHosting):
[Export]
class MyAddin
{
public String myData { get { return "The data!"; } }
}
class MyProgram
{
[Import]
public MyAddin myAddin { get; set; }
}
class Program
{
static void Main(string[] args)
{
AggregateCatalog catalog = new AggregateCatalog();
catalog.Catalogs.Add(new AssemblyCatalog(typeof(MyAddin).Assembly));
CompositionContainer _container = new CompositionContainer(catalog);
MyProgram myProgram = new MyProgram();
_container.SatisfyImportsOnce(myProgram);
Console.WriteLine(myProgram.myAddin.myData);
Console.ReadLine();
_container.Dispose();
}
}
But when I try to compile it, this error message is generated:
Error 2 The best overloaded method match for
'System.ComponentModel.Composition.Hosting.CompositionContainer.SatisfyImportsOnce(System.ComponentModel.Composition.Primitives.ComposablePart)'
has some invalid
arguments X:\Dev\S-L\CSharp\EtceteraSolution\CompositionContainer_Demo\CompositionContainer_Main.cs 15 13 CompositionContainer_Demo
Sample source: http://msdn.microsoft.com/en-us/library/system.componentmodel.composition.hosting.compositioncontainer%28v=vs.110%29.aspx

You are missing extension method that can do it. You just need to add correct using on top of your program. I guess the example doesn't show the necessary usings.
The method you're looking for is: public static ComposablePart SatisfyImportsOnce(this ICompositionService compositionService, object attributedPart);
Add using System.ComponentModel.Composition on your program, and the extension method should work fine.
Alternatively, it's also possible to call extensionmethod like this:
AttributedModelServices.SatisfyImportsOnce(_container, myProgram);
Note, it's in .NET framework >= 4.0.

Related

Having similar method name with same parameter inside a class just with Interface name change

Just came across a code where a method with the same name is implemented within the class twice.
Once with the name only
Second with the Interface name and then the method name.
What is the concept called? I am unable to find the right direction. And if someone can explain it that would be great.
// Online C# Editor for free
// Write, Edit and Run your C# code using C# Online Compiler
using System;
public class HelloWorld
{
public static void Main(string[] args)
{
var obj = new AuthClass();
Console.WriteLine(obj.Login());
var obj2 = new AuthClass() as IAuth;
Console.WriteLine(obj2.Login());
//------------
}
}
public class AuthClass : IAuth
{
public string Login()
{
return "Method : You can be a developer";
}
string IAuth.Login()
{
return "Interface: Please learn the concepts";
}
}
public interface IAuth
{
string Login();
}

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 do I dynamically call a class and use it's functions?

I have a problem trying to dynamically call my class. This is my example code:
Class:
namespace TestUseCase
{
public class UseCase11
{
public UseCase11()
{
}
public string init()
{
return "aa.aspx";
}
}
}
Method to call the class:
private void dynamicExecution(string ClassName, string FunctionName)
{
System.Reflection.Assembly assembly = System.Reflection.Assembly.GetEntryAssembly();
Object[] para = new Object[1];
para[0] = null;
object dynMyClass = assembly.CreateInstance(ClassName);
dynMyClass.GetType().GetMethod(FunctionName).Invoke(dynMyClass, para);
}
Usage:
dynamicExecution("TestUseCase.UseCase11", "init");
Unfortunately the result is always null. How can I resolve this issue?
Make sure that the class you are attempting to instantiate is declared in the right assembly. In your example you are using Assembly.GetEntryAssembly() but is that the correct assembly? If the class is defined in the same assembly as the code that you have shown you could also use Assembly.GetExecutingAssembly().

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.

Satisfying imports for an existing object using MEF

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).

Categories