0

We are trying to implement repository pattern in using Linq2SQl and the data context is initialized lazily.

Repository class implements IRepository

public class Repository<T> : IRepository<T> where T : class
{
        private readonly Table<T> _table;

        public Repository(IDataContextAdapter dataContextAdapter)
        {
            _table = dataContextAdapter.Context.GetTable<T>();
        }
...
}

Data Access uses delegates to Repository

public class UserDataAccess : IUserDataAccess
{
    private readonly IRepository<User> _userRepository;

    public UserDataAccess(IDataContextAdapter dataContextAdapter, 
        Func<IDataContextAdapter, IRepository<User>> userRepository)
    {
        _userRepository = userRepository(dataContextAdapter);
    }
 }  

I like to know how to define the repositories generically in unity container.

Currently I have the following, but I don't want to repeat it for every concrete repository class like User, Employer etc.

UnityContainer.RegisterType<Func<IDataContextAdapter, IRepository<User>>>(
    new InjectionFactory(c => 
                    new Func<IDataContextAdapter, IRepository<User>>(
                        context => new Repository<User>(context))
        )
 );

I am looking for a way to define the types generically, something like

  UnityContainer.RegisterType<Func<IDataContextAdapter, IRepository<T>>>(
        new InjectionFactory(c => 
                        new Func<IDataContextAdapter, IRepository<T>>(
                            context => new Repository<T>(context))
            )
     );

I have tried applying typeof operation with on '<>', but didn't had much success.

skjagini
  • 3,142
  • 5
  • 34
  • 63
  • How do you resolve your registrations/dependencies? Can you give an example? – Andrew Savinykh Mar 16 '11 at 09:24
  • Also can you explain what are you trying to achieve with a) Unity and b) with the delegate? Is there any cases where when you pass IDataContextAdapter to the UserDataAccess class but the repository that gets created is not created by call of new Repository(_idatacontextadapter), where _idatacontextadapter is the IDataContextAdapter that was passed to UserDataAccess? I.e. what kind of variation are you trying to model via the delegate? – Andrew Savinykh Mar 16 '11 at 10:07
  • And the last question is, why do you need a repository per table at all? It's quite unusual and rarely useful. – Andrew Savinykh Mar 16 '11 at 10:34
  • @zespri : DataContextAdapter is invoked at the runtime, and the repositories and data access classes cannot be initialized until then due to my own constrains, and auto factories are designed to solve the same problem. Take a look at this question for background, http://stackoverflow.com/questions/5171779/dependency-injection – skjagini Mar 16 '11 at 13:37
  • Ok, still don't see a need for delegates. I have updated my answer below, could you please reply what is it you want to achieve that the suggested solution does not achieve. – Andrew Savinykh Mar 16 '11 at 21:06
  • Having two datacontexts is only part of the problem, and I don't like the solution you are providing even then, if the presenter class needs to save data into both the DataContext's, need to pass two different sets of DataAccess's classes for the constructor.
    The main reason for using delegates in DataAccess is to instantiate them when needed instead of creating them at the beginning of the unity container. For eg. your app has multiple tabs and user can work submit work at the same time. If you initiate the DataContext at the beginning of the app, it would be shared by all tabs.
    – skjagini Mar 17 '11 at 14:24
  • And I also don't want to depend on UnityContainer, instead the dependencies should be resolved through constructor injection. If you are still not clear about the requirements, I am going to blog about it, will post a link with full source to get a clear picture. – skjagini Mar 17 '11 at 16:36
  • You have to depend on UnitiyContainer even if in terms of assembly dependency. Unity container's life time is the whole duration of your application run time, it's always there and you already depend on it for resolving your dependencies, automatically or not. Can you tell me what benefit you perceive in not having to "depend" on Unity in this case? Make the instance of the container a static public property in a class, and access it from everywhere in your app. This is pretty standard. – Andrew Savinykh Mar 17 '11 at 20:12
  • I added more information to my answer to address your "initiate the DataContext at the beginning of the app" concern. – Andrew Savinykh Mar 17 '11 at 20:13
  • Take a look into the "answer" for the question, http://stackoverflow.com/questions/5171779/dependency-injection and notice that you are not using unity any where to resolve dependencies. In Web application a context is created and disposed at the end of each request and it is maintained unique for each request, not affecting other contexts. I am trying to achieve the same in windows and not to depend on Unity inside presenter methods. Calling Unity to resolve inside presenter methods is anti pattern. Try updating your solution using the answer provided. – skjagini Mar 17 '11 at 20:40
  • "notice that you are not using unity any where to resolve dependencies" I'm not sure what you mean by that. I agree that there is no explicit call to unity, I understand that, but it hardly matters because unity is still there and it's unity, that do the resolution. Also could you expand on why you think that "Calling Unity to resolve inside presenter methods is anti pattern". – Andrew Savinykh Mar 17 '11 at 21:23
  • So with your automatic resolution, how are you intending to inject a particular instance of IDataContextAdapter? Let's assume for a second that your attempt to use '<>' worked. When UserDataAccess is instantiated, where IDataContextAdapter for it comes from? – Andrew Savinykh Mar 17 '11 at 21:49
  • 1. Your presenters are coupled with Unity and have direct knowledge about and you cannot move onto a new DI container in the future. 2. What is the need for DI container if you can resolve the same by calling some static method inside your methods. 3. Search for constructor injection vs setter methods to know the importance of constructor injection. If you instantiate class, the class should be fully initialized through constructor and should not depend on static methods, containers, concrete classes, setter methods to run any of its methods – skjagini Mar 17 '11 at 21:53
  • "presenters have direct knowledge about unity": when you are not writing a library, you select one container and you use it. How often did you have to change a DI container mid project? I understand this argument if you were righting a library that needs a DI but the particular DI is defined by the user of the library, not the library itself. Designing end-user application so that you can easily replace DI container later is hardly practical and by doing this you forfeit benefits of the particular container that you've chosen, because you are bound to use only common feature in all containers. – Andrew Savinykh Mar 17 '11 at 21:55
  • "what is the need for DI container". A good answer is here http://stackoverflow.com/questions/871405/why-do-i-need-an-ioc-container-as-opposed-to-straightforward-di-code Note that in this accepted answer the author uses the Resolve method =) I also can add to this tha DI are extremely good for TDD, so that you can replace parts of your system with fakes/mocks for better testability. – Andrew Savinykh Mar 17 '11 at 22:12
  • If you could clear up for me the question about IDataContextAdapter above, I feel that we could get a bit further. Thanks. – Andrew Savinykh Mar 17 '11 at 22:13
  • Please take a look into authors arguments behind constructor injection, http://misko.hevery.com/2009/02/19/constructor-injection-vs-setter-injection/ It works the same for setter injection or using containers inside the methods. I don't care much about point 1, though you can build your applications in such a way other than bootstrapper no other parts of your application know about DI. – skjagini Mar 17 '11 at 22:21
  • @zespri : http://stackoverflow.com/questions/2176833/ioc-resolve-vs-constructor-injection – skjagini Mar 31 '11 at 15:42
  • @zespri I get what the original poster is trying to accomplish [Autofac](http://code.google.com/p/autofac) already supports [this](http://nblumhardt.com/2010/01/the-relationship-zoo/) in a feature called auto generated factories. – Damian Apr 12 '11 at 20:47

2 Answers2

0

I can't understand what you are trying to achieve, but I make a suggestion as to what is the closes semi-logical thing in my mind is.

First loose your delegate. (Or explain what it's for). Define your UserDataAccess this way:

public class UserDataAccess : IUserDataAccess
{
    private readonly IRepository<User> _userRepository;

    public UserDataAccess(IRepository<User> userRepository)
    {
        _userRepository = userRepository;
    }
} 

Now your registration will look something like this:

        DataContextAdapter context = new DataContextAdapter();
        UnityContainer unityContainer = new UnityContainer();
        unityContainer.RegisterType(typeof (IRepository<>), typeof (Repository<>));
        unityContainer.RegisterType<IUserDataAccess, UserDataAccess>();
        unityContainer.RegisterInstance<IDataContextAdapter>(context);

And then you resolve like this:

        IUserDataAccess test = unityContainer.Resolve<IUserDataAccess>();

UserDataAccess will be created and the right closed type Repoistory<> will be injected into the constructor. In turn, DataContextAdapter will be injected in the constructor of Repoistory<>.

UPDATE 1

Based on the information in the original question, link to that you provided above, is there a reason why the following won't work for you?

        unityContainer.RegisterType(typeof (IRepository<>), typeof (Repository<>));
        unityContainer.RegisterType<IUserDataAccess, UserDataAccess>();

        DataContextAdapter context1 = new DataContextAdapter();
        DataContextAdapter context2 = new DataContextAdapter();

        IUnityContainer container1 = unityContainer.CreateChildContainer();
        IUnityContainer container2 = unityContainer.CreateChildContainer();

        container1.RegisterInstance<IDataContextAdapter>(context1);
        container2.RegisterInstance<IDataContextAdapter>(context2);

        IUserDataAccess test1 = container1.Resolve<IUserDataAccess>();
        IUserDataAccess test2 = container2.Resolve<IUserDataAccess>();

I still see no reason for the complexity with delegates and injection factory. You need different data contexts in different code path, so just inject different instances in your container as shown below. You can dispose of a container when you no longer need it.

Is there is anything else from your requirements that left unfulfilled by this solution?

UPDATE 2

In response to yor comment above, I'd like to clarify, that you don't have to register or instantiate contexts upfront with the approach above. You can do it right at the site you are using them:

        // When you need context, obtain it
        DataContextAdapter context1 = new DataContextAdapter();

        //Register it for the local scope
        IUnityContainer container1 = unityContainer.CreateChildContainer();
        container1.RegisterInstance<IDataContextAdapter>(context1);

        // Resolve the dependency
        IUserDataAccess test1 = container1.Resolve<IUserDataAccess>();

        // Use your interface
          ......

        // Release and dispose your context
        container1.Dispose

The main point to take away is that's you who control where and when instantiate them

Andrew Savinykh
  • 25,351
  • 17
  • 103
  • 158
0

.NET does not allow for partially closed types. http://www.lostechies.com/blogs/jimmy_bogard/archive/2009/09/01/partially-closed-generic-types.aspx This is why you can't do what you are attempting to achieve in a generic way. In runtime you either can have open type like Func<,> or closed type like Func<IDataContextAdapter, IRepository<User>>

Simplifying, Unity maintains a dictionary of type mappings where from type is a non-generic type or generic open type or generic closed type. Thus it is impossible to map a type that does not fall into these categories.

If we could come up with a good and fast way to match against Func<IDataContextAdapter, IRepository<T>> at run time, it would be possible to write an extension to Unity that does the resolution. However it does not seem that it would be possible to do such matching without using reflections, and you normally try to avoid using reflection every time you resolve a type for performance reasons. At worst case you use reflection during the first resolution only to generated IL on the fly that would do the object creation without reflection afterwards. Unfortunately in our case this would be impossible.

The only way to resolve this on Unity level that I see is every time Func<IDataContextAdapter, IRepository<Something>> is requested is to check if this is already registered and if not register it with generated on the fly factory.

In other words there are no simple ways of doing exactly this.

An alternative I can suggest is do this multiple registrations in a bootstrapper style, but you are already aware of this option.

You also can define a generic factory like this:

public class GenericDataServiceFactory<TResult, TModel>
{
    private UnityContainer container;
    private Func<IDataContextAdapter, IRepository<TModel>> _repositoryFactory;

    public GenericDataServiceFactory(Func<IDataContextAdapter, IRepository<TModel>> repositoryFactory)
    {
        _repositoryFactory = repositoryFactory;
    }

    public TResult CreateUserDataAccess(IDataContextAdapter dataContextAdapter)
    {
        Type targerType = typeof (TResult);
        // Via reflection find constructor like this
        // TResult(IDataContextAdapter dataContextAdapter, Func<IDataContextAdapter,IRepository<Something>> repositoryFactory)
        // Invoke it with dataContextAdapter and _repositoryFactory and return the result

        return newObject;
    }
}

But then again, you are going through reflection every time, and I'm sure you don't want to do that.

Andrew Savinykh
  • 25,351
  • 17
  • 103
  • 158
  • Thanks Zespri for taking time, you can define open generics using type of operator, for example, http://davidhayden.com/blog/dave/archive/2008/03/25/UnityDependencyInjectionOpenGenericTypes.aspx I am just trying to do the same with delegates. The easiest way for now: http://stackoverflow.com/questions/5344195/converting-from-closed-generics-to-open-generics – skjagini Mar 18 '11 at 05:11