MEF Property Export with PartCreationPolicy - ioc-container

When I try to do this:
[Export(typeof(IMyService))]
[PartCreationPolicy(CreationPolicy.Shared)]
private MyService Service
{
get
{
var service = new MyService();
service.Configure();
return service;
}
}
I get a compile error: Attribute 'PartCreationPolicy' is not valid on this declaration type. It is only valid on 'class' declarations.
Is this a bug? I don't see why MEF would allow property exports but not allow one to specify the part lifetime.
Using VS2010 RC.

The PartCreationPolicy should go on the class, even if the export goes on the property. The class is what corresponds to the part, and the creation policy will control whether MEF creates a new instance of the class each time an export is requested from it or not.
I am not sure whether you want to use Shared or NonShared. You have the CreationPolicy set to Shared in your code example, but then you are creating a new instance of MyService in your property getter. That seems to indicate you may be looking for a creation policy of NonShared.
If you do want a new service to be created each time an export is requested, you should do it via the creation policy, and not by creating a new instance in the getter. The value of an export is not supposed to change at runtime, and in fact MEF will only call the getter once, and store the return value for when it needs to access the exported value again. So creating a new instance in your getter can make it look like there would be multiple services created when there will actually only be one.

Related

How to pass a runtime parameter as part of the dependency resolution for a generic class?

A similar question has been answered here:
How can I pass a runtime parameter as part of the dependency resolution?
However, I was wondering how this can be done when registering a generic class?
Normally, I would register it as following:
services.AddScoped(typeof(ITest<>), typeof(Test<>));
But what if I want to pass a runtime parameter to constructor? Without using DI, it would be something like:
new Test<MyClass>(string mystring, int myInt)
In the linked answer it's suggests using a factory method but this is giving me an error if I don't pass it the exact type.
The alternative would be to get an instance without passing a runtime parameter in the constructor and instead using a setter method after getting exact instance. I would like to avoid this however because every time after getting instance you must remember to call setter method.
Is there some way around it? I guess I could use some factory class instead of registering it in startup class...
EDIT:
After reading Steven's answer which was very useful, I updated question with more concrete example:
Following example is inside some method:
//instance of repository are passed inside constructor of class
//calling some to update/insert
//IMPORTANT - calling external service I want save parameters to db no matter what
using(var ctx=new DbContext())
{
//create log object
ctx.logs.add(Obj)
ctx.save()
}
//some code after
Let's say I want to be consistent and call method of my loggingrepository and there add logging object and save everything to database
However, every repository in constructor accepts DbContext, which is registered as scoped (durig one request).
If it's inside transaction, saving depends about code after calling external service and it can throw exception and save nothing.
So yeah, I could create new dbContext and pass it in logging method or call some private logging function and save inside it,
but point is that if I would ask for instance of loggingRepository I would want DI to pass this localy created dbContext variable to constructor
and not one registered as scoped inside startup method, so that addind and saving log happens no matter what external service or code after calling it does.
My situation in something similar, but it's going for some data in db based on current user and I don't wanna pass same parameter to numerous method, but only inside class constructor.
The general solution in injecting primitive configuration values into your application components, is to extract them into a Parameter Object. This gives those values a new, unambiguous type, which can be registered into your container:
// Parameter Object
public TestConfiguration
{
public string Mystring;
public int MyInt;
}
// (Generic) class using the Parameter Object
public class Test<T>
{
public Test(TestConfiguration config) { ... }
}
// Registering both
services.AddScoped(typeof(ITest<>), typeof(Test<>));
services.AddSingleton(new TestConfiguration { Mystring = ..., Myint = ... });
Configuration values are not considered to be runtime data as their values are known at startup and constant for the duration of the application. That's why you can supply them to the constructors of your application components.
Real runtime data, however, should not be passed on to a component during construction. Runtime data are values that are not known at startup and typically passed along by the user through a web request, are retrieved from the database, session, or anything that can change during the lifetime of the application.
Instead of passing runtime data in through the constructor, you should either:
Pass runtime data through method calls of the API or
Retrieve runtime data from specific abstractions that allow resolving runtime data.
You can find more information about passing runtime data here.

Access Business Classes in WCF methods

I have an asmx web service I am converting to WCF. In the old structure I had a number of web service methods that accessed business classes to do the work. For example:
public DataSet GetAppointmentDataToConvert(string aAccessToken, string aStartingId)
{
//verify that the user is allowed to use this web service
if (!isAuthorized(aAccessToken))
{
throw new Exception("Not authorized");
}
cls256_BitEncryptionConversion cls256 = new cls256_BitEncryptionConversion();
return cls256.GetAppointmentDataToConvert(aStartingId);
}
This method initialized the cls256_BitEncryptionConversion class and called a method inside it to do the work, then returned the result.
I am trying to set up a WCF Service that will use the cls256_BitEncryptionConversion class, but despite both the class and the service being in the same namespace, my service method is unable to "see" the class. What am I doing wrong?
These are few tips for you to resolve it your self:
Make it sure that even they have the same namespace are they in the same project?
If they are in different project add it as you reference where you want to use it. And probably add a using directive if necessary.
I was able to resolve the issue by restructuring the project. I moved all the classes from the app_code folder into the root of the project.

connection string injection

I am trying to learn Ninject and started with what I thought is very simple thing. Can't make it work. Obviously, I am missing something basic.
So, I have this little console application that listens for WCF calls on a certain port and saves data that come via WCF to a database. There are 3 projects in the solution: 1. data access library, 2. WCF stuff and 3. console acting as a host. Ninject is not used yet. So the dependencies between projects are like this: 3 -> 2 -> 1
I want to start with injecting connection string that console host takes from its config into data access library. Googling for ninjection of connection string brought some examples, but they are not complete.
One of the examples suggested to bind in the host's Main() like this:
static void Main(string[] args)
{
new StandardKernel().Bind<ConnectionStringProvider>().ToConstant(
new ConnectionStringProvider { ConnectionString = Config.ConnectionString });
}
where ConnectionStrinProvider is a simple class that contains only one property ConnectionString. What I can't figure out is how do I instantiate ConnectionStrinProvider in the data access library. I tried
var csprovider = new StandardKernel().Get<ConnectionStringProvider>();
it doesn't work - meaning that it returns new instance of the provider instead of the one that was created during binding. I also tried to add .InSingletonScope() to the binding, with the same result.
You need to keep a reference to the kernel you set up. It doesn't work if you instantiate it every time.
public static IKernel Ninject {get; private set;}
static void Main(string[] args)
{
Ninject = new StandardKernel()
Ninject.Bind<ConnectionStringProvider>().ToConstant(
new ConnectionStringProvider { ConnectionString = Config.ConnectionString });
}
On the consummer side, you can call the Ninject static property on your main.
Obvious note aside: this is sample code, on production code you may want to make a better design for that global static variable.
The kernel is what keeps track of all the bindings for you. However, you are creating a new instance each time. That won't work. Instead, create the kernel and then store it off (here I'm storing it off in a local variable, but you'd probably want to store it in a field in some class):
var connectionStringProvider = new ConnectionStringProvider { ConnectionString = Config.ConnectionString };
var kernel = new StandardKernel().Bind<ConnectionStringProvider>().ToConstant(connectionStringProvider);
Now obtain instances by accessing the existing kernel.
var csprovider = kernel.Get<ConnectionStringProvider>();
That being said, using it in this fashion is the wrong way to go about it, as this pattern is known as a service locator pattern, which is the antitheses of dependency injection. Generally speaking, you have a top-level class (for example, your application class with the Main method) that is either obtained via Kernel.Get or injected via Kernel.Inject, and all other dependencies are injected normally through constructors or [Inject]'ed properties.
Also, there are usually plugins available for most situations so that you don't have to instantiate the kernel yourself. However, I'm not aware of one for console apps.

Binding custom entity collection to an ADF table

I create a method on the session facade, that returns a custom entity collection.
I publish it in the local interface.
I bind corresponding data control iterator to an ADF table.
When run, it shows "No data to display".
There are no exceptions in the weblogic console.
public List<Users> getCollection() {
List<Users> l = new ArrayList<Users>();
Users u = em.find(Users.class, new BigDecimal(999));
System.out.println(u.getName());
l.add(u);
return l;
}
When I invoke this method via another method, bound to a ADF button,
all is fine though.
User name is printed to the weblogic console.
public int printCollectionSize() {
return getCollection().size();
}
When I bind to an ADF table a data control iterator created from (autogenerated) method getUsersFindAll, all is fine too.
public List<Users> getUsersFindAll() {
return em.createNamedQuery("Users.findAll").getResultList();
}
I am completely lost. Is my method never gets executed by the data binding system? What is wrong with it?
In ADF all of the code and bindings in the JSP page are simply properties values used for ADF when it begins auto-generating code to link between JSP and the backing bean. So first and foremost I'm not sure (though I'm no expert) as to whether you can easily bind ADF components to just any collection.
Best bet to start with is to find a way to call a method directly early on that ensures the collection has been initialized, then refresh the table. Perhaps use a command button with full refresh so you don't have to worry about any PPR oddities.

JEE6 application session scoped objects

I'm still pretty new to JEE6 having come from a Servlets + JSP style of development on legacy systems. In the applications I worked on we would just throw objects into the various supplied scopes (request, session and application) keyed on a constant String. For example, the User object that represented the currently logged in user would be in the session scope keyed under "current_user".
I've done the same in our new JEE6 application, when the user logs in the User object is bound into the session scope. I'm wondering though if there is a better, more EE, way of handling this?
The problem I'm having is that now I've got the User stored in the session it's awkward to get access to it again. I can get it via JNDI look up or with a few lines of boiler plate code involving FacesContext but neither are very elegant.
Rather than boiler plate code all over the place (the User object is need in a few places) it would be great if I could just get the object injected into a field or method. After all there can only be one object in the session bound to a particular name so there shouldn't be any ambiguity about what I'm asking for. Is this possible?
Maybe the CDI could be of any help?
Could you define the way you achieve the User object into one, main method?
If so, and you're working with Java EE 6 environment, you could use the Producer method. Something between these lines:
public class ClassWhichCanAccessUserObject {
#Produces
public User produceUser() {
User u = ... // get the user as you do it right now
return u;
}
}
Then in the place you want to use this class you just Inject it (in the field or method) and use it:
public class MyLogic {
#Inject
User u;
}
You need to remember to add the beans.xml file to your classpath, as without the CDI will not work for your module.