C# 使用生存期范围时如何处理运行时参数?
警告,前方有长柱 我最近一直在思考这个问题,我正在努力找到一个令人满意的解决方案。我将使用C#和autofac作为示例 问题 IoC非常适合构建大型无状态服务树。我解析服务并只将数据传递给方法调用。太好了 有时,我希望将数据参数传递到服务的构造函数中。这就是工厂的目的。我没有解析服务,而是解析其工厂,并使用参数调用create方法来获取服务。稍微多做点工作,但还行 有时,我希望我的服务在某个范围内解析到同一个实例。Autofac提供了非常方便的C# 使用生存期范围时如何处理运行时参数?,c#,dependency-injection,inversion-of-control,autofac,object-lifetime,C#,Dependency Injection,Inversion Of Control,Autofac,Object Lifetime,警告,前方有长柱 我最近一直在思考这个问题,我正在努力找到一个令人满意的解决方案。我将使用C#和autofac作为示例 问题 IoC非常适合构建大型无状态服务树。我解析服务并只将数据传递给方法调用。太好了 有时,我希望将数据参数传递到服务的构造函数中。这就是工厂的目的。我没有解析服务,而是解析其工厂,并使用参数调用create方法来获取服务。稍微多做点工作,但还行 有时,我希望我的服务在某个范围内解析到同一个实例。Autofac提供了非常方便的InstancePerLifeTimeScope()
InstancePerLifeTimeScope()
。它允许我始终解析到执行子树中的同一实例。好
有时我想将这两种方法结合起来。我需要构造函数中的数据参数,并对实例的作用域进行了限定。我还没有找到一个令人满意的方法来实现这一点
解决
1.初始化方法
不要将数据传递给构造函数,只需将其传递给Initialize
方法即可
界面:
interface IMyService
{
void Initialize(Data data);
void DoStuff();
}
class MyService : IMyService
{
private Data mData;
public void Initialize(Data data)
{
mData = data;
}
public void DoStuff()
{
//...
}
}
builder.RegisterType<MyService>().As<IMyService>().InstancePerLifetimeScope();
var myService = context.Resolve<IMyService>();
myService.Init(data);
// somewhere else
var myService = context.Resolve<IMyService>();
interface IMyService
{
void DoStuff();
}
class MyService : IMyService
{
private Data mData;
public MyService(IDataHolder dataHolder)
{
mData = dataHolder.Data;
}
public void DoStuff()
{
//...
}
}
builder.RegisterType<MyService>().As<IMyService>();
builder.RegisterType<DataHolder>().As<IDataHolder>().InstancePerLifetimeScope();
var holder = context.Resolve<IDataHolder>();
holder.Data = data;
// somewhere else
var myService = context.Resolve<IMyService>();
interface IMyService
{
void DoStuff();
}
class MyService : IMyService
{
private Data mData;
public MyService(Data data)
{
mData = dataHolder.Data;
}
public void DoStuff()
{
//...
}
}
builder.RegisterType<MyService>().As<IMyService>().InstancePerLifetimeScope();
var myServiceFactory = context.Resolve<Func<Data, IMyService>>();
myServiceFactory(data);
// somewhere else
var myService = context.Resolve<IMyService>();
类别:
interface IMyService
{
void Initialize(Data data);
void DoStuff();
}
class MyService : IMyService
{
private Data mData;
public void Initialize(Data data)
{
mData = data;
}
public void DoStuff()
{
//...
}
}
builder.RegisterType<MyService>().As<IMyService>().InstancePerLifetimeScope();
var myService = context.Resolve<IMyService>();
myService.Init(data);
// somewhere else
var myService = context.Resolve<IMyService>();
interface IMyService
{
void DoStuff();
}
class MyService : IMyService
{
private Data mData;
public MyService(IDataHolder dataHolder)
{
mData = dataHolder.Data;
}
public void DoStuff()
{
//...
}
}
builder.RegisterType<MyService>().As<IMyService>();
builder.RegisterType<DataHolder>().As<IDataHolder>().InstancePerLifetimeScope();
var holder = context.Resolve<IDataHolder>();
holder.Data = data;
// somewhere else
var myService = context.Resolve<IMyService>();
interface IMyService
{
void DoStuff();
}
class MyService : IMyService
{
private Data mData;
public MyService(Data data)
{
mData = dataHolder.Data;
}
public void DoStuff()
{
//...
}
}
builder.RegisterType<MyService>().As<IMyService>().InstancePerLifetimeScope();
var myServiceFactory = context.Resolve<Func<Data, IMyService>>();
myServiceFactory(data);
// somewhere else
var myService = context.Resolve<IMyService>();
注册:
interface IMyService
{
void Initialize(Data data);
void DoStuff();
}
class MyService : IMyService
{
private Data mData;
public void Initialize(Data data)
{
mData = data;
}
public void DoStuff()
{
//...
}
}
builder.RegisterType<MyService>().As<IMyService>().InstancePerLifetimeScope();
var myService = context.Resolve<IMyService>();
myService.Init(data);
// somewhere else
var myService = context.Resolve<IMyService>();
interface IMyService
{
void DoStuff();
}
class MyService : IMyService
{
private Data mData;
public MyService(IDataHolder dataHolder)
{
mData = dataHolder.Data;
}
public void DoStuff()
{
//...
}
}
builder.RegisterType<MyService>().As<IMyService>();
builder.RegisterType<DataHolder>().As<IDataHolder>().InstancePerLifetimeScope();
var holder = context.Resolve<IDataHolder>();
holder.Data = data;
// somewhere else
var myService = context.Resolve<IMyService>();
interface IMyService
{
void DoStuff();
}
class MyService : IMyService
{
private Data mData;
public MyService(Data data)
{
mData = dataHolder.Data;
}
public void DoStuff()
{
//...
}
}
builder.RegisterType<MyService>().As<IMyService>().InstancePerLifetimeScope();
var myServiceFactory = context.Resolve<Func<Data, IMyService>>();
myServiceFactory(data);
// somewhere else
var myService = context.Resolve<IMyService>();
类别:
interface IMyService
{
void Initialize(Data data);
void DoStuff();
}
class MyService : IMyService
{
private Data mData;
public void Initialize(Data data)
{
mData = data;
}
public void DoStuff()
{
//...
}
}
builder.RegisterType<MyService>().As<IMyService>().InstancePerLifetimeScope();
var myService = context.Resolve<IMyService>();
myService.Init(data);
// somewhere else
var myService = context.Resolve<IMyService>();
interface IMyService
{
void DoStuff();
}
class MyService : IMyService
{
private Data mData;
public MyService(IDataHolder dataHolder)
{
mData = dataHolder.Data;
}
public void DoStuff()
{
//...
}
}
builder.RegisterType<MyService>().As<IMyService>();
builder.RegisterType<DataHolder>().As<IDataHolder>().InstancePerLifetimeScope();
var holder = context.Resolve<IDataHolder>();
holder.Data = data;
// somewhere else
var myService = context.Resolve<IMyService>();
interface IMyService
{
void DoStuff();
}
class MyService : IMyService
{
private Data mData;
public MyService(Data data)
{
mData = dataHolder.Data;
}
public void DoStuff()
{
//...
}
}
builder.RegisterType<MyService>().As<IMyService>().InstancePerLifetimeScope();
var myServiceFactory = context.Resolve<Func<Data, IMyService>>();
myServiceFactory(data);
// somewhere else
var myService = context.Resolve<IMyService>();
注册:
interface IMyService
{
void Initialize(Data data);
void DoStuff();
}
class MyService : IMyService
{
private Data mData;
public void Initialize(Data data)
{
mData = data;
}
public void DoStuff()
{
//...
}
}
builder.RegisterType<MyService>().As<IMyService>().InstancePerLifetimeScope();
var myService = context.Resolve<IMyService>();
myService.Init(data);
// somewhere else
var myService = context.Resolve<IMyService>();
interface IMyService
{
void DoStuff();
}
class MyService : IMyService
{
private Data mData;
public MyService(IDataHolder dataHolder)
{
mData = dataHolder.Data;
}
public void DoStuff()
{
//...
}
}
builder.RegisterType<MyService>().As<IMyService>();
builder.RegisterType<DataHolder>().As<IDataHolder>().InstancePerLifetimeScope();
var holder = context.Resolve<IDataHolder>();
holder.Data = data;
// somewhere else
var myService = context.Resolve<IMyService>();
interface IMyService
{
void DoStuff();
}
class MyService : IMyService
{
private Data mData;
public MyService(Data data)
{
mData = dataHolder.Data;
}
public void DoStuff()
{
//...
}
}
builder.RegisterType<MyService>().As<IMyService>().InstancePerLifetimeScope();
var myServiceFactory = context.Resolve<Func<Data, IMyService>>();
myServiceFactory(data);
// somewhere else
var myService = context.Resolve<IMyService>();
类别:
interface IMyService
{
void Initialize(Data data);
void DoStuff();
}
class MyService : IMyService
{
private Data mData;
public void Initialize(Data data)
{
mData = data;
}
public void DoStuff()
{
//...
}
}
builder.RegisterType<MyService>().As<IMyService>().InstancePerLifetimeScope();
var myService = context.Resolve<IMyService>();
myService.Init(data);
// somewhere else
var myService = context.Resolve<IMyService>();
interface IMyService
{
void DoStuff();
}
class MyService : IMyService
{
private Data mData;
public MyService(IDataHolder dataHolder)
{
mData = dataHolder.Data;
}
public void DoStuff()
{
//...
}
}
builder.RegisterType<MyService>().As<IMyService>();
builder.RegisterType<DataHolder>().As<IDataHolder>().InstancePerLifetimeScope();
var holder = context.Resolve<IDataHolder>();
holder.Data = data;
// somewhere else
var myService = context.Resolve<IMyService>();
interface IMyService
{
void DoStuff();
}
class MyService : IMyService
{
private Data mData;
public MyService(Data data)
{
mData = dataHolder.Data;
}
public void DoStuff()
{
//...
}
}
builder.RegisterType<MyService>().As<IMyService>().InstancePerLifetimeScope();
var myServiceFactory = context.Resolve<Func<Data, IMyService>>();
myServiceFactory(data);
// somewhere else
var myService = context.Resolve<IMyService>();
注册:
interface IMyService
{
void Initialize(Data data);
void DoStuff();
}
class MyService : IMyService
{
private Data mData;
public void Initialize(Data data)
{
mData = data;
}
public void DoStuff()
{
//...
}
}
builder.RegisterType<MyService>().As<IMyService>().InstancePerLifetimeScope();
var myService = context.Resolve<IMyService>();
myService.Init(data);
// somewhere else
var myService = context.Resolve<IMyService>();
interface IMyService
{
void DoStuff();
}
class MyService : IMyService
{
private Data mData;
public MyService(IDataHolder dataHolder)
{
mData = dataHolder.Data;
}
public void DoStuff()
{
//...
}
}
builder.RegisterType<MyService>().As<IMyService>();
builder.RegisterType<DataHolder>().As<IDataHolder>().InstancePerLifetimeScope();
var holder = context.Resolve<IDataHolder>();
holder.Data = data;
// somewhere else
var myService = context.Resolve<IMyService>();
interface IMyService
{
void DoStuff();
}
class MyService : IMyService
{
private Data mData;
public MyService(Data data)
{
mData = dataHolder.Data;
}
public void DoStuff()
{
//...
}
}
builder.RegisterType<MyService>().As<IMyService>().InstancePerLifetimeScope();
var myServiceFactory = context.Resolve<Func<Data, IMyService>>();
myServiceFactory(data);
// somewhere else
var myService = context.Resolve<IMyService>();
builder.RegisterType();
用法:
interface IMyService
{
void Initialize(Data data);
void DoStuff();
}
class MyService : IMyService
{
private Data mData;
public void Initialize(Data data)
{
mData = data;
}
public void DoStuff()
{
//...
}
}
builder.RegisterType<MyService>().As<IMyService>().InstancePerLifetimeScope();
var myService = context.Resolve<IMyService>();
myService.Init(data);
// somewhere else
var myService = context.Resolve<IMyService>();
interface IMyService
{
void DoStuff();
}
class MyService : IMyService
{
private Data mData;
public MyService(IDataHolder dataHolder)
{
mData = dataHolder.Data;
}
public void DoStuff()
{
//...
}
}
builder.RegisterType<MyService>().As<IMyService>();
builder.RegisterType<DataHolder>().As<IDataHolder>().InstancePerLifetimeScope();
var holder = context.Resolve<IDataHolder>();
holder.Data = data;
// somewhere else
var myService = context.Resolve<IMyService>();
interface IMyService
{
void DoStuff();
}
class MyService : IMyService
{
private Data mData;
public MyService(Data data)
{
mData = dataHolder.Data;
}
public void DoStuff()
{
//...
}
}
builder.RegisterType<MyService>().As<IMyService>().InstancePerLifetimeScope();
var myServiceFactory = context.Resolve<Func<Data, IMyService>>();
myServiceFactory(data);
// somewhere else
var myService = context.Resolve<IMyService>();
var myservicecfactory=context.Resolve();
myServiceFactory(数据);
//其他地方
var myService=context.Resolve();
对。我不会将工厂调用的结果存储在任何地方,因为autofac会为我存储它。这对于任何阅读代码的人来说都是非常令人惊讶的。我不确定autofac是否打算这样使用。这样做的好处是,我既不需要额外的初始化方法,也不需要额外的类来保存实例
问题:
你对此有何看法?如何处理具有运行时数据参数和生存期范围的情况?我是否缺少更好的方法?大多数时候,运行时数据是在任何过程中都需要传递的非静态信息,如数学函数中的
x
,因此最简单的处理方法是在函数中使用参数:
class MyService : IMyService
{
public MyService(){}
public void DoStuff(Data mData)
{
//...
}
}
var myService = context.Resolve<IMyService>();
myService.DoStuff(data);
2.-如果您在解析的每个位置都没有对运行时数据的引用,那么您可以在何时何地创建运行时数据。由于
//初始化
var builder=new ContainerBuilder();
builder.RegisterType();
var container=builder.Build();
//创建或修改运行时数据的位置。当运行时数据更改时,必须再次更新容器。
var mData=新数据(“运行时数据”);
updatedBuilder=新的ContainerBuilder();
updatedBuilder.RegisterInstance(mData).As
updatedBuilder.Update(builder);
//在应用程序的任何位置
使用(var scope=updatedBuilder.BeginLifetimeScope())
{
var service=scope.Resolve();
service.DoStuff();
}
//在应用程序的任何其他点
使用(var scope=updatedBuilder.BeginLifetimeScope())
{
var service2=scope.Resolve();
服务2.DoStuff();
}
我对这一点的看法是,你已经尽了最大努力。关于这一点,我唯一的不满是Autofac在帮助您管理这些生命周期范围方面并没有做得很好,因此您只能在某个地方调用它们的BeginLifetimeScope
并且它们可以嵌套
另一方面,Ninject做了一些非常酷的事情,不需要把你的大脑翻过来。它们使您可以创建一个(gasp)命名的范围,并绑定该范围内对象的生存期。如果您使用的是工厂(从问题来看,显然是这样),那么您还需要使用上下文保留扩展,这样在工厂外激活的东西就可以从工厂激活的指定范围中获得生命周期管理。绑定最终看起来像这样:
var scopeName = "Your Name Here";
Bind<TopLevelObject>().ToSelf().DefinesNamedScope(ScopeName);
Bind<ISomeScopedService>().To<SomeScopedService>().InNamedScope(ScopeName);
// A minor bit of gymnastics here for factory-activated types to use
// the context-preservation extension.
Bind<FactoryActivatedType>().ToSelf().InNamedScope(ScopeName);
Bind<IFactoryActivatedType>().ToMethod(x => x.ContextPreservingGet<FactoryActivatedType>());
var scopeName=“您的名字在这里”;
Bind().ToSelf().DefinesNamedScope(ScopeName);
Bind().To().InNamedScope(ScopeName);
//这里有一点小技巧供工厂激活类型使用
//上下文保存扩展。
Bind().ToSelf().InNamedScope(ScopeName);
Bind().ToMethod(x=>x.ContextPreservingGet());
这一点的好处在于,这些绑定的范围专门绑定到命名的范围,而不仅仅绑定到链上最近的生存期范围。实际上,它使这些对象的生命周期更加可预测。许多IoC框架支持注册工厂函数(或lambda表达式),该函数将容器/范围/解析上下文本身的实例作为其参数之一 这允许使用额外级别的间接寻址,以及使用唯一标识上下文或范围的信息。此外,许多提供了钩子,如事件处理程序或从生命周期范围类派生的选项,以与正在启动或结束的范围交互 原则 对于AutoFac和您的特定示例,以下原则将起作用,在注册中使用额外的间接级别
// Inject `Data` instance resolved from current scope.
builder.Register<IMyService>(ctx => new MyService(ctx.Resolve<Data>()));
// Extra level of indirection, get a "factory" for a 'Data' instance.
builder.Register<Data>(ctx => ctx.Resolve<Func<Data>>()()).InstancePerLifetimeScope();
// The indirection resolves to a map of scopes to "factory" functions.
builder.Register<Func<Data>>(ScopedDataExtensions.GetFactory);
如果我理解正确,您希望通过将对象创建委托给容器,同时将一些参数传递给其构造函数来使用工厂 这是在温莎城堡实施的 我们要解析的示例类:
public interface IMyService
{
void Do();
}
public class MyService : IMyService
{
private readonly Data _data;
private readonly IDependency _dependency;
public MyService(Data data, IDependency dependency)
{
_data = data;
_dependency = dependency;
}
public void Do()
{
throw new System.NotImplementedException();
}
}
public class Data
{
}
public interface IDependency
{
}
public class Dependency : IDependency
{
}
我们创建一个工厂界面:
public interface IMyServiceFactory
{
IMyService Create(Data data);
void Release(IMyService service);
}
我们不会实现此接口,因为Castle Windsor将使用动态代理生成一个实现。这里有一个重要的细节:工厂方法中的参数名(数据)和