MEF Recomposition error - export

I get the exception:
1) More than one export was found that matches the constraint:
ContractName CompositionTest.C
RequiredTypeIdentity CompositionTest.C
When running the program
namespace CompositionTest
{
// [Export] // Also doesn't work
[Export(typeof(C))]
public class C
{
//[ImportAttribute(AllowRecomposition = true)] // also doesn't work
[Import(AllowRecomposition = true)]
public C PropertyC { get; set; }
}
class Program
{
static void Main(string[] args)
{
// Declare a composition container.
CompositionContainer compositionContainer = new CompositionContainer();
compositionContainer.ComposeParts( new C() );
compositionContainer.ComposeParts( new C() ); // exception here!
}
}
}
What am I doing wrong?

The first time you call ComposeParts, a new C object is added as an export to the container. Then second time you call ComposeParts, another C object is added as an export. This creates a problem with the import because there are two possible parts for import and MEF cannot make a decision. Hence the cardinality exception.
One solution would be to change the import to:
[ImportMany(AllowRecomposition = true)]
public IEnumerable<C> PropertyC { get; set; }
Another solution is to actually use a catalog when creating the container. This is the common way to use MEF. Pretty much all the examples you can find follow this approach:
//Create a catalog. In this case, a catalog based on an already loaded assembly.
var catalog = new AssemblyCatalog(typeof(C).Assembly);
//Create a container using the catalog. Only the parts from that catalog will be used.
var compositionContainer = new CompositionContainer(catalog);
For more on catalogs you should read this article.
By the way I have never seen such an example of MEF usage before. My answer is mainly based on observations I made while debugging it.

Related

How to use Dapper's SqlBuilder?

I can't find any documentation or examples I can follow to use the SqlBuilder class.
I need to generate sql queries dynamically and I found this class. Would this be the best option?
the best place to start is to checkout the dapper source code from its github repo and have a look at the SqlBuilder code. The SqlBuilder class is only a 200 lines or so and you should be able to make an informed choice on whether it is right for your needed.
An other option is to build your own. I personally went down this route as it made sense. Dapper maps select querys directly to a class if you name your class properties the same as your database or add an attribute such as displayName to map from you can use reflection to get the property names. Put there names and values into a dictionary and you can genarate sql fairly easy from there.
here is something to get you started:
first an example class that you can pass to your sqlbuilder.
public class Foo
{
public Foo()
{
TableName = "Foo";
}
public string TableName { get; set; }
[DisplayName("name")]
public string Name { get; set; }
[SearchField("fooId")]
public int Id { get; set; }
}
This is fairly basic. Idea behind the DisplayName attribute is you can separate the properties out that you want to include in your auto generation. in this case TableName does not have a DisplayName attribute so will not be picked up by the next class. however you can manually use it when generating your sql to get your table name.
public Dictionary<string, object> GetPropertyDictionary()
{
var propDictionary = new Dictionary<string, object>();
var passedType = this.GetType();
foreach (var propertyInfo in passedType.GetProperties())
{
var isDef = Attribute.IsDefined(propertyInfo, typeof(DisplayNameAttribute));
if (isDef)
{
var value = propertyInfo.GetValue(this, null);
if (value != null)
{
var displayNameAttribute =
(DisplayNameAttribute)
Attribute.GetCustomAttribute(propertyInfo, typeof(DisplayNameAttribute));
var displayName = displayNameAttribute.DisplayName;
propDictionary.Add(displayName, value);
}
}
}
return propDictionary;
}
This method looks at the properties for its class and if they are not null and have a displayname attribute will add them to a dictionary with the displayname value as the string component.
This method is designed to work as part of the model class and would need to be modified to work from a separate helper class. Personally I have it and all my other sql generation methods in a Base class that all my models inherit from.
once you have the values in the dictionary you can use this to dynamically generate sql based on the model you pass in. and you can also use it to populate your dapper DynamicParamaters for use with paramiterized sql.
I hope this helps put you on the right path to solving your problems.

How come my ContextInitializer for EF 6 has zero refrences?

I'm trying to learn EF 6 Code-first in WPF by following some tutorials. Since I'm familiar with model-first I can understand most parts except I've found ContextInitializer a little confusing. I defined a ContextInitializer like this code:
public class ContextInitializer : DropCreateDatabaseIfModelChanges<Context>
{
protected override void Seed(Context context)
{
var customers = new List<Customer>
{
new Customer{Name="Jane",Phone="2238718"},
new Customer{Name="David",Phone="43245608"},
new Customer{Name="Mike",Phone="90814417"}
};
customers.ForEach(cu => context.Customers.Add(cu));
context.SaveChanges();
}
}
and this is my Context class:
public class Context : DbContext
{
public Context()
: base("MVVM")
{
}
public DbSet<Customer> Customers { get; set; }
}
and It created a database at first run which I think it's weird because this class has zero refrences. Since Seed method doesn't fire again, I can't understand how this works.
Can someone explain to me how my ContextInitializer with zero reference created a database?
Does the following section exist in your App.Config?
<contexts>
<context type="(your name space).Context, MVVM">
<databaseInitializer type="(your name space).ContextInitializer, MVVM" />
</context>
</contexts>
If it is, the program knows where to look to find the ContextInitializer. If the database already exists and the tables in the database already match those of the POCO/model classes, nothing happens. If the model has changed or the database doesn’t exist, this class will be invoked, resulting in the database being seeded with your data.

Importing a class with a specific parameter

I got a ViewModel which I export with MEF. I'd like this ViewModel to be initialized differently each time it's being imported, according to an enum/specific object parameter that will be provided to it.
I've been reading a little on the subject and I found that maybe this -
http://msdn.microsoft.com/en-us/library/ee155691.aspx#metadata_and_metadata_views
would be able to fit my needs, but I'm not sure that this would be the best way to do it.
Another method I've been thinking about is importing the class normally, and then once I've an instance, to call a special initialization method that would receive my parameter. However this doesn't seem like a classic MEF implementation, and maybe losses some of its "magic".
I'm hoping someone would be able to point out for me what would be the recommended method to achieve this.
Thanks!
A workaround is exporting a factory that creates instances of your type. While this means you cannot directly import thos instances, it does have the benefit that the logic to create them is the responsability of the factory so users of the class do not have to know about it:
public class ServiceWithParameter
{
public ServiceWithParameter( int a )
{
this.a = a;
}
private readonly int a;
}
[Export]
public class ServiceWithParameterFactory
{
public ServiceWithParameterFactory()
{
instance = 0;
}
public ServiceWithParameter Instance()
{
return new ServiceWithParameter( instance++ );
}
private int instance;
}
//now everywhere you need ServiceWithParameter:
[Import]
ServiceWithParameterFactory serviceFactory;
var instanceA = serviceFactory.Instance(); //instanceA.a = 0
var instanceB = serviceFactory.Instance(); //instanceB.a = 1
A more extensible way is telling the container you have a factory and an example is presented here: http://pwlodek.blogspot.com/2010/10/mef-object-factories-using-export.html

How to use singleton over multiple assemblies in design time

I have 3 assemblies:
MyApp.Views (uses MyApp.Data and MyApp.Metadata)
MyApp.Data (uses MyApp.Metadata)
MyApp.Metadata
I have an interface, say IMetadata. Then, I also have an implementation in MyApp.Metadata which I register in a singleton class:
IoCContainer.Instance.Register<IMetadata, Metadata>();
Then, in design time, I use an assembly that needs to use the metadata (but it's the MyApp.Data that resolves the type):
IoCContainer.Instance.ResolveType<IMetadata>();
But this fails. The IoCContainer.Instance does not contain the same interfaces (actually, it's empty). The singleton implementation is really basic:
public class IoCContainer
{
static IoCContainer()
{
Instance = new IoCContainer();
}
public static IoCContainer Instance { get; private set; }
}
Somehow, it looks like separate assemblies are loaded in separate app domains (or something like that). Anyone knows a solution for this?
Could be a threading issue. Your singleton instance could be instantiated twice by different threads. Have a look at http://www.yoda.arachsys.com/csharp/singleton.html. It explains it in more detail and provides you with a thread safe solution.
Ok, problem seems to be solved. It might have 2 causes:
First, sometimes visual studio "updates" your references to shared libraries so one points to the bin\debug\mysharedassembly.dll, and the other one still points to ....\lib\mysharedassembly. This is some kind of stupid behavior of VS2010 where it tries to outthink the developer.
Second, I had this definition of the IoC Container:
public class IoCContainer
{
static IoCContainer()
{
Instance = new IoCContainer();
}
private IoCContainer()
{
}
public static IoCContainer Instance { get; private set; }
}
Which I changed to:
public class IoCContainer
{
private static readonly IoCContainer _instance = new IoCContainer;
private IoCContainer()
{
}
public static IoCContainer Instance { get { return _instance; } }
}
Anyway, problem solved :)

Winforms: access class properties throughout application

I know this must be an age-old, tired question, but I cant seem to find anything thru my trusty friend (aka Google).
I have a .net 3.5 c# winforms app, that presents a user with a login form on application startup. After a successful login, I want to run off to the DB, pull in some user-specific data and hold them (in properties) in a class called AppCurrentUser.cs, that can thereafer be accessed across all classes in the assembly - the purpose here being that I can fill some properties with a once-off data read, instead of making a call to the DB everytime I need to. In a web app, I would usually use Session variables, and I know that the concept of that does not exist in WinForms.
The class structure resembles the following:
public class AppCurrentUser {
public AppCurrentUser() { }
public Guid UserName { get; set; }
public List<string> Roles { get; set; }
public string Firstname { get; set; }
public string Lastname { get; set; }
}
Now, I have some options that I need some expert advice on:
Being a "dumb" class, I should make the properties non-static, instantiate the class and then set the properties...but then I will only be able to access that instance from within the class that it was created in, right?
Logically, I believe that these properties should be static as I will only be using the class once throughout the application (and not creating new instances of it), and it's property values will be "reset" on application close. (If I create an instance of it, I can dispose of it on application close)
How should I structure my class and how do I access its properties across all classes in my assembly? I really would appreciate your honest and valued advice on this!!
Thanks!
Use the singleton pattern here:
public class AppUser
{
private static _current = null;
public static AppUser Current
{
get { return = _current; }
}
public static void Init()
{
if (_current == null)
{
_current = new AppUser();
// Load everything from the DB.
// Name = Dd.GetName();
}
}
public string Name { get; private set; }
}
// App startup.
AppUser.Init();
// Now any form / class / whatever can simply do:
var name = AppUser.Current.Name;
Now the "static" things are thread-unsafe. I'll leave it as an exercise of the reader to figure out how to properly use the lock() syntax to make it thread-safe. You should also handle the case if the Current property is accessed before the call to Init.
It depends on how you setup your architecture. If you're doing all your business logic code inside the actual form (e.g. coupling it to the UI), then you probably want to pass user information in as a parameter when you make a form, then keep a reference to it from within that form. In other words, you'd be implementing a Singleton pattern.
You could also use Dependency Injection, so that every time you request the user object, the dependency injection framework (like StructureMap) will provide you with the right object. -- you could probably use it like a session variable since you'll be working in a stateful environment.
The correct place to store this type of information is in a custom implementation of IIdentity. Any information that you need to identify a user or his access rights can be stored in that object, which is then associated with the current thread and can be queried from the current thread whenever needed.
This principal is illustrated in Rocky Lhotka's CLSA books, or google winforms custom identity.
I'm not convinced this is the right way but you could do something like this (seems to be what you're asking for anyway):
public class Sessions
{
// Variables
private static string _Username;
// properties
public static string Username
{
get
{
return _Username;
}
set
{
_Username = value;
}
}
}
in case the c# is wrong...i'm a vb.net developer...
then you'd just use Sessions.USername etc etc

Resources