6

假设我有 IRepository 接口及其实现 SqlRepository,它将 LINQ 作为 SQL DataContext 的参数。假设我有 IService 接口及其实现服务,它需要三个 IRepository、IRepository 和 IRepository。演示代码如下:

public interface IRepository<T> { }

public class SqlRepository<T> : IRepository<T>
{
    public SqlRepository(DataContext dc) { ... }
}

public interface IService<T> { }

public class Service<T,T1,T2,T3> : IService<T>
{
    public Service(IRepository<T1> r1, IRepository<T2>, IRepository<T3>) { ... }
}

在创建服务类时是否可以通过相同的 DataContext 注入所有三个存储库?

4

4 回答 4

8

您需要做的就是确保在向DatacontextUnity 容器注册时使用PerResolveLifetimeManager配置中的任一:

<type type="<namespace>.DataContext, <assembly>">
    <lifetime type="Microsoft.Practices.Unity.PerResolveLifetimeManager, Microsoft.Practices.Unity" />
</type>

或在代码中:

container.RegisterType<DataContext>(new PerResolveLifetimeManager());

then whenever the container resolves the Service any dependencies which also require a DataContext will be provided with exactly the same one. But the next request to resolve Service will create a new DataContext.

于 2011-04-04T16:41:52.420 回答
3

我想我知道你想做什么。我在同一条船上,正在尝试提出解决方案。

我的服务层对即将到来的请求执行操作,它的作用取决于内容。它将它传递给一系列责任类。我希望在调用的服务方法的生命周期内将相同的上下文传递给所有类

您可以指定 PerResolveLifetimeManager。到目前为止,它似乎正在处理我的测试用例:

服务等级:

public interface IServiceClass
{
    void DoService();
}

class ServiceClass : IServiceClass
{
    private IHandler Handler { get; set; }

    public ServiceClass(IHandler handler)
    {
        Handler = handler;
    }

    public void DoService()
    {
        Handler.HandleRequest();
    }
}

IHandler 由两个类实现,并执行责任链模式:

    public interface IHandler
{
    void HandleRequest();
}

class Handler : IHandler
{
    private IDataContext DataContext { get; set; }
    public Handler(IDataContext dataContext)
    {
        DataContext = dataContext;
    }

    public void HandleRequest()
    {
        DataContext.Save("From Handler 1");
    }
}

class Handler2 : IHandler
{
    private IDataContext DataContext { get; set; }
    private IHandler NextHandler { get; set; }

    public Handler2(IDataContext dataContext, IHandler handler)
    {
        DataContext = dataContext;
        NextHandler = handler;
    }

    public void HandleRequest()
    {
        if (NextHandler != null)
            NextHandler.HandleRequest();

        DataContext.Save("From Handler 2");
    }
}

如您所见,两个处理程序都接受一个 IDataContext 实例,我希望它们在它们中都相同。Handler2 也接受一个 IHandler 的实例来传递控制权(它在此处进行演示,但实际上,只有一个会处理请求......)

数据上下文。在构造函数中,我初始化了一个 Guid,并在它的操作过程中输出它,以便我可以查看它的调用是否使用相同的实例:

public interface IDataContext
{
    void Save(string fromHandler);
}

class DataContext : IDataContext
{
    private readonly Guid _guid;

    public DataContext()
    {
        _guid = Guid.NewGuid();
    }

    public void Save(string fromHandler)
    {
        Console.Out.WriteLine("GUI: [{0}] {1}", _guid, fromHandler);
    }
}

最后是服务的注册和调用:

    private IUnityContainer container;
    private void InitializeUnity()
    {
        container = new UnityContainer();
        container.RegisterType<IHandler, Handler2>("Handler2",
            new InjectionConstructor(new ResolvedParameter<IDataContext>(), new ResolvedParameter<IHandler>("Handler1")));
        container.RegisterType<IHandler, Handler>("Handler1");
        container.RegisterType<IDataContext, DataContext>(new PerResolveLifetimeManager());
        container.RegisterType<IServiceClass, ServiceClass>("MyClass", new InjectionConstructor(new ResolvedParameter<IHandler>("Handler2")));
    }

    private void CallService()
    {
        var service = container.Resolve<ServiceClass>("MyClass");
        service.DoService();

        // Resolving and calling again to simulate multiple resolves:
        service = container.Resolve<ServiceClass>("MyClass");
        service.DoService();
    }

这是我得到的输出:

GUI: [f2250055-8a5f-4f80-a1b6-bcc5574138cf] From Handler 1
GUI: [f2250055-8a5f-4f80-a1b6-bcc5574138cf] From Handler 2
GUI: [22a5c0a3-3c5c-4683-807d-bf2b43f3cd0a] From Handler 1
GUI: [22a5c0a3-3c5c-4683-807d-bf2b43f3cd0a] From Handler 2

希望这堵文字墙回答了您的问题...如果不是很抱歉,它确实激发了我需要实施的解决方案...

于 2010-05-29T18:45:10.767 回答
0

如果我正确理解了您的问题(并且如果您使用的是统一...我想您这样做是因为您已将其标记为统一),则可以执行以下操作:

在您的存储库实现中,

[InjectionConstructor]
public SqlRepository(
    [Dependency] DataContext ctx)

但是您必须以相同的方式标记服务构造器并使用容器来解析您的服务以及存储库。DataContext 也必须在容器中才能使其工作。

另一种方法是对您的存储库执行以下操作:

[InjectionMethod]
public void Initialize(
    [Dependency] DataContext ctx

这将告诉统一调用此方法,如果您将在您的服务构造函数中使用 Unity 和 BuildUp 方法......像这样:

unitycontainer.BuildUp<IRepository>(repository);

我想这不是您要找的,但请告诉我我是否走在正确的轨道上,我会看看是否可以进一步帮助您...

干杯/J

于 2009-05-23T15:25:15.923 回答
0

您是否尝试过对统一容器使用 RegisterInstance() 方法?像这样的东西可能会起作用:

公共静态 UnityContainer CreateContainer() { UnityContainer 容器 = new UnityContainer();

        try
        {
            var section = ConfigurationManager.GetSection("unity") as UnityConfigurationSection;

            if (section != null)
            {
                section.Containers[0].Configure(container);
            }
        }
        catch (Exception ex)
        {
            TraceLogger.LogMessage("Configurarion Error for Unity Container", ex.Message, TraceEventType.Critical);
            Environment.Exit(1);
        }


        container.RegisterInstance(new DataContext());
        return container;
    }

现在,每次此容器尝试构建需要 DataContext 的对象时,都会传递相同的实例。您甚至可以在注册它的实例之前配置 DataContext。

更新:一个选择(现在,我不知道这是否真的是一个好习惯,但这对我有用)是为您要创建的每个对象创建一个不同的容器。就像是:

UnityContainer container1 = ContainerFactory.CreateContainer();
UnityContainer container2 = ContainerFactory.CreateContainer();
UnityContainer container3 = ContainerFactory.CreateContainer();
MyObject1 object1 = container1.Resolve<MyObject1>();
MyObject2 object2 = container2.Resolve<MyObject2>();
MyObject3 object3 = container3.Resolve<MyObject3>();

或更概括的方式:

MyObject1 object1 = ContainerFactory.CreateContainer().Resolve<MyObject1>();
MyObject1 object2 = ContainerFactory.CreateContainer().Resolve<MyObject2>();
MyObject1 object3 = ContainerFactory.CreateContainer().Resolve<MyObject3>();

嗯,有很多方法可以做到这一点,创建一个列表,使用工厂模式。希望能帮助到你

于 2009-05-29T16:45:41.950 回答