views:

1363

answers:

7

I am considering using Unity to manage the lifetime of a custom user class instance. I am planning on extending the LifetimeManager with a custom ASP.NET session manager. What I want to be able to do is store and retrieve the currently logged in user object from my custom classes, and have Unity get the instance of User from the session object in ASP.NET, or (when in a Win32 project) retrieve it statically or from the current thread.

So far my best solution is to create a static instance of my Unity container on startup, and use the Resolve method to get my User object from each of my classes. However, this seems to create a dependency on the unity container in my other classes. What is the more "Unity" way of accomplishing this goal? I would like to be able to read/replace the current User instance from any class.

A: 

I would think that you need two services that you expose through unity (or one service that does both actions).

Instead of storing the user object, store an interface implementation which exposes a method/property that will get the user object for you. In the ASP.NET case, you retrieve the user from the session. In the WinForm solution (or whatever), you can get it from the executing thread.

You would also have a set method/property as well, which you would use to set the user.

casperOne
Can you provide a Pseudocode example? I don't understand how your response uses Unity, or how it allows a single class to retrieve the user without knowing if the class is being used in ASP.NET or a WinForm.
A: 

Sounds like actually you need Registry pattern, not Unity.

http://martinfowler.com/eaaCatalog/registry.html

Lex Li
+1  A: 

Why not use the cache object instead...then you can use it both from win and web. Like this:

    IUnityContainer container= HttpRuntime.Cache.Get("Unity") as IUnityContainer;

    if (container == null)
    {
        container= // init container

        HttpRuntime.Cache.Add("Unity",
            container,
            null,
            Cache.NoAbsoluteExpiration,
            Cache.NoSlidingExpiration,
            CacheItemPriority.NotRemovable,
            null);
    }

    // return container or something

HttpRuntime.Cache will work both in win and web

Johan Leino
A: 

My apologies if this isn't quite right but ...

Unity is a game dev platform, therefore I assume that you are building a 3d app or game that you intend to do something cool with (e.g. make it multiplayer / track users progress using the server).

Why not have each user login, then you can use the MembershipProvider and Formsauthentication classes to gain acces to the users id / name.

On your server you simply link all information to that for the user allowing you easily pull back (simple ajax / normal http request) data relevant to the situation / users request.

I don't know this for sure but i believe that unity is something that deploys client side therefore no integration with it needs to be done on the server.

Simply request what you need and process it on the client side.

That way you stick to the classic n-tier design pattern that allows you separate your logic from your data storage and ui.

Hope this helps ...

Wardy
Sorry but your answer just points to a completely different path instead of providing a solution to a very concise question.
JCallico
Wrong Unity, check out http://unity.codeplex.com/. It's a dependency injection library.
marijne
+3  A: 

You'd get the best bang with Unity when used with ASP.Net MVC rather than the plain old ASP.Net project. ASP.Net MVC allows you to use a container like Unity to manage the user objects, controllers, models, etc. If possible, use MVC rather than ASP.net web forms for your projects.

If I understand your question correctly, you would want to use Unity to maintain the lifetime of the object to per session. You need to implement a SessionLifetimeManager that extends LifetimeManager. The code is pretty simple and goes along these lines:

public class SessionLifetimeManager : LifetimeManager
{
    private string _key = Guid.NewGuid().ToString();

    public override object GetValue()
    {
          return HttpContext.Current.Session[_key];
    }

    public override void SetValue(object value)
    {
          HttpContext.Current.Session[_key] = value;
    }

    public override void Remove()
    {
          HttpContext.Current.Session.Remove(_key);
    }
}

You could also write a similar one for PerWebRequest lifetime management.

Ravi
A: 

Maybe I am over thinking this but I think you should use AoP along with IoC. It is really a beautiful pairing. Essentially what I would do is hijack the constructor of the classes that you are resolving, otherwise called creating an aspect. You could then inject the user into the class on entry to the constructor, but whatever is resolving the class doesn't explicitly have to provide the user thus preventing a pairing to Unity itself.

PostSharp is an excellent AoP framework IMHO.

Now in the end your app will be dependent on the AoP framework, but a completely decoupled application may be unrealistic depending on your environment. You may be surprised how useful the combination of AoP and IoC can be.

joshlrogers
A: 

If by "a custom ASP.NET session manager" you are talking about an NHibernate Session or a Data/ObjectContext, it sounds like what you need is an IUserRepository injected into either the constructor or property setter from which you could retrieve the User object. The implementation of IUserRepository could be anything from database access to a backend cache, etc. If you are using .Resolve() on the container directly, you are following the Service Locator pattern and not properly using Unity for all that it can provide.

You can then use Ravi's answer to manage the lifetime of the repository.

Ryan Riley