Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/304.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 是Func<;T>;构造函数中的参数是否会降低IoC解析速度?_C#_Inversion Of Control_Unity Container_Simple Injector - Fatal编程技术网

C# 是Func<;T>;构造函数中的参数是否会降低IoC解析速度?

C# 是Func<;T>;构造函数中的参数是否会降低IoC解析速度?,c#,inversion-of-control,unity-container,simple-injector,C#,Inversion Of Control,Unity Container,Simple Injector,我正在努力提高IoC容器的性能。我们使用的是Unity和SimpleInjector,我们有一个具有此构造函数的类: public AuditFacade( IIocContainer container, Func<IAuditManager> auditManagerFactory, Func<ValidatorFactory> validatorCreatorFactory, IUserContext userContext,

我正在努力提高IoC容器的性能。我们使用的是Unity和SimpleInjector,我们有一个具有此构造函数的类:

public AuditFacade(
    IIocContainer container, 
    Func<IAuditManager> auditManagerFactory,
    Func<ValidatorFactory> validatorCreatorFactory, 
    IUserContext userContext,
    Func<ITenantManager> tenantManagerFactory, 
    Func<IMonitoringComponent> monitoringComponentFactory)
    : base(container, auditManagerFactory, GlobalContext.CurrentTenant, 
          validatorCreatorFactory, userContext, tenantManagerFactory)
{
    _monitoringComponent = new Lazy<IMonitoringComponent>(monitoringComponentFactory);
}
public AuditTenantComponent(Func<IAuditTenantRepository> auditTenantRepository)
{
    _auditTenantRepository = new Lazy<IAuditTenantRepository>(auditTenantRepository);
}
public-AuditFacade(
iIOC集装箱,
Func auditManagerFactory,
Func validatorCreatorFactory,
IUserContext用户上下文,
Func租户管理工厂,
功能监控组件(工厂)
:base(容器、auditManagerFactory、GlobalContext.CurrentTenant、,
validatorCreatorFactory、userContext、tenantManagerFactory)
{
_monitoringComponent=新延迟(monitoringComponentFactory);
}
我还有另一个具有此构造函数的类:

public AuditFacade(
    IIocContainer container, 
    Func<IAuditManager> auditManagerFactory,
    Func<ValidatorFactory> validatorCreatorFactory, 
    IUserContext userContext,
    Func<ITenantManager> tenantManagerFactory, 
    Func<IMonitoringComponent> monitoringComponentFactory)
    : base(container, auditManagerFactory, GlobalContext.CurrentTenant, 
          validatorCreatorFactory, userContext, tenantManagerFactory)
{
    _monitoringComponent = new Lazy<IMonitoringComponent>(monitoringComponentFactory);
}
public AuditTenantComponent(Func<IAuditTenantRepository> auditTenantRepository)
{
    _auditTenantRepository = new Lazy<IAuditTenantRepository>(auditTenantRepository);
}
public AuditTenantComponent(Func AuditTenantPository)
{
_AuditEnterpository=新的惰性(AuditEnterpository);
}

我看到第二个问题在1毫秒内得到解决,大多数情况下,而第一个问题平均需要50-60毫秒。我相信慢一点的原因是因为参数,它有更多的参数。但是我如何才能提高这个较慢的程序的性能呢?我们使用
Func
作为参数,这是事实吗?如果这是造成速度缓慢的原因,我可以改变什么?

您所做的每件事都有与之相关的成本。通常,递归解析的构造函数参数越多,花费的时间就越长。但是你必须决定费用是可以的还是太高


在您的情况下,50毫秒是否会造成瓶颈?您是只创建一个实例,还是在一个紧密的循环中吐出它们?仅将1毫秒与50毫秒进行比较可能会导致您谴责速度较慢的一个,但是如果用户无法判断50毫秒已经过去,并且不会在应用程序的其他地方造成问题,那么如果您不知道需要它,为什么要运行环圈以加快速度呢?

您可以连接到简单注入器的管道并添加配置文件,这允许您发现哪些类型创建速度较慢。以下是您可以使用的扩展方法:

public struct ProfileData{
公共只读表达式BuildingEventArgs信息;
公共只读时间间隔已过;
公共配置文件数据(ExpressionBuildingEventArgs信息,时间跨度){
this.Info=Info;
this.appead=已过;
}
}
静态void enableprofileing(容器、列表profileLog){
container.ExpressionBuilding+=(s,e)=>{
Func profilingWrapper=创建者=>{
var watch=Stopwatch.StartNew();
var instance=creator.Invoke();
Add(新的ProfileData(e,watch.appeased));
返回实例;
};
Func instanceCreator=
表达式.Lambda(e.Expression.Compile();
e、 Expression=Expression.Convert(
表达式.调用(
表达式.Constant(profilingWrapper),
表达式.常量(instanceCreator)),
e、 了解执行类型);
};
}
您可以按如下方式使用它:

container.Register<IMonitoringComponent>(() => new LazyMonitoringComponentProxy(
    new Lazy<IMonitoringComponent>(container.GetInstance<CostlyMonitoringComp>));
var container=newcontainer();
//TODO:您的注册在这里。
//钩住探查器
列表档案日志=新列表(1000);
//注册后再打电话。
启用配置文件(容器、配置文件日志);
//触发验证以允许预编译所有内容。
container.Verify();
profileLog.Clear();
//解析类型:
container.GetInstance();
//按时间顺序显示解析时间。
var slowestFirst=profileLog.OrderByDescending(line=>line.appeased);
foreach(最慢的var行优先)
{
Console.WriteLine(string.Format(“{0}ms:{1}”),
line.Info.knownImplementType.Name,
行。已用。总毫秒);
}
请注意,显示的时间包括解决依赖关系所需的时间,但这可能会让您很容易知道是什么类型导致延迟

关于这里给出的代码,我想注意两件重要的事情:

  • 此代码将对解析对象图的性能产生严重的负面影响,并且
  • 代码不是线程安全的

  • 因此,不要在您的生产环境中使用它。

    您当前的设计可能有很多需要改进的地方。这些改进可以分为五类,即:

  • 可能滥用基类
  • 服务定位器反模式的使用
  • 环境上下文反模式的使用
  • 漏洞百出的抽象
  • 在注入构造函数中执行太多操作
  • 可能滥用基类 一般的共识是,您应该更喜欢。继承经常被过度使用,并且与使用组合相比通常会增加更多的复杂性。通过继承,派生类与基类实现紧密耦合。我经常看到基类被用作实用工具类,其中包含各种用于横切的帮助器方法一些派生类可能需要的问题和其他行为

    通常更好的方法是一起删除基类,并将服务注入到实现中(在您的例子中是
    AuditFacade
    类)这仅仅暴露了服务所需的功能。或者,在交叉关注点的情况下,根本不注入该行为,而是使用扩展类的行为的交叉关注点来包装实现

    在您的例子中,我认为复杂的情况显然正在发生,因为7个注入依赖项中有6个没有被实现使用,而是只传递给基类。换句话说,这6个依赖项是基类的实现细节,而实现仍然被迫知道它们。通过抽象(部分)在服务背后的基类中,您可以将
    AuditFacade
    需要的依赖项数量减少到两个依赖项:
    Func
    和新的抽象。该抽象背后的实现将有6个构造函数依赖项,但
    a