小编Ste*_*ven的帖子

代码合同比 对象初始化器(.net 4.0)

从表面看,对象初始化器似乎对.net 4.0"代码契约"提出了问题,通常在对象构造函数完成时应该建立不变量.然而,据推测,对象初始化器需要在构造完成后设置属性.

我的问题是,"代码契约"的不变量是否能够处理对象初始化器,"好像"属性是在构造函数完成之前设置的?那确实非常好!!

.net design-by-contract .net-4.0 object-initializers code-contracts

14
推荐指数
1
解决办法
1025
查看次数

Autofac:开放泛型类型的批量注册

我得到了一个具有许多具体类型的程序集,IHandler<TCommand>如下所示:

public class MoveCustomerHandler : IHandler<MoveCustomerCommand>
{
    void IHandler<MoveCustomerCommand>.Handle(MoveCustomerCommand c)
    {
        // some business logic for moving a customer.
    }
}
Run Code Online (Sandbox Code Playgroud)

目前,我正按照以下方式逐一注册:

builder.RegisterType<MoveCustomerHandler>()
    .As<IHandler<MoveCustomerCommand>>();

builder.RegisterType<ProcessOrderHandler>()
    .As<IHandler<ProcessOrderCommand>>();

builder.RegisterType<SomeOtherFancyHandler>()
    .As<IHandler<SomeOtherFancyCommand>>();

// Many handler registrations here...
Run Code Online (Sandbox Code Playgroud)

使用构造函数注入注入命令处理程序,如下所示:

public class OrderController
{
    private readonly IHandler<ProcessOrderCommand> handler;

    public OrderController(IHandler<ProcessOrderCommand> handler)
    {
        this.handler = handler;
    }
}
Run Code Online (Sandbox Code Playgroud)

有没有办法使用Autofac以简单的方式批量注册我的所有处理程序?

.net c# dependency-injection ioc-container autofac

14
推荐指数
1
解决办法
4265
查看次数

Autofac:隐藏一个复合背后的多个逆变实现

我被这个关于(.NET 4.0)协方差和逆向支持Autofac的问题引发了,现在我正试图实现类似的东西,但没有任何运气.

我试图做到的,是在这样的方式配置Autofac,当我解决一个具体的IEventHandler<TEvent>(使用示范的目的container.Resolve,但通常的过程中使用构造器注入),Autofac将返回我MultipleDispatchEventHandler<TEvent>是包装所有注册的事件处理程序,它可分配来自请求的处理程序.

换句话说,当我写这个:

var handler = container
    .GetInstance<IEventHandler<CustomerMovedEvent>>();

handler.Handle(new CustomerMovedEvent());
Run Code Online (Sandbox Code Playgroud)

关于应用程序设计(如下所示),我希望MultipleDispatchEventHandler<CustomerMovedEvent>返回包含a CustomerMovedEventHandler和a的应用程序NotifyStaffWhenCustomerMovedEventHandler.

这是应用程序设计:

// Events:
public class CustomerMovedEvent { }

public class CustomerMovedAbroadEvent : CustomerMovedEvent { }

public class SpecialCustomerMovedEvent : CustomerMovedEvent { }


// Event handler definition (note the 'in' keyword):
public interface IEventHandler<in TEvent> 
{
    void Handle(TEvent e);
}

// Event handler implementations:
public class CustomerMovedEventHandler
    : IEventHandler<CustomerMovedEvent>
{
    public void Handle(CustomerMovedEvent …
Run Code Online (Sandbox Code Playgroud)

c# dependency-injection ioc-container covariance autofac

14
推荐指数
2
解决办法
2090
查看次数

MVC 4 Autofac和Generic Repository模式

我正在使用我的MVC 4应用程序中的工作单元和通用存储库模式.我试图解决的问题是为我系统中的每个实体创建Repository存根.为了利用Autofac Ioc,我必须为每个实体创建一个存储库类和接口,以便我可以在Autofac中注册它.

应用开始......

builder.RegisterType<SchoolDetailRepository>().As<ISchoolDetailRepository>().InstancePerHttpRequest();
Run Code Online (Sandbox Code Playgroud)

存储库类

 public class SchoolDetailRepository : RepositoryBase<SchoolDetail>, ISchoolDetailRepository
{
    public SchoolDetailRepository(IDatabaseFactory databaseFactory) : base(databaseFactory)
    {
    }
}
Run Code Online (Sandbox Code Playgroud)

接口

public interface ISchoolDetailRepository : IRepository<SchoolDetail>
{
}
Run Code Online (Sandbox Code Playgroud)

这似乎是很多额外的工作.

有没有办法注册Type的通用存储库而不是创建所有这些空类?

然后在我的服务类中,我可以通过Ioc将泛型类型传递给构造函数,例如...

public class SchoolService : ISchoolService
{
    private readonly IRepository<SchoolDetail> _schoolRepository;
    private readonly IUnitOfWork _unitOfWork;

    public SchoolService(IRepository<SchoolDetail> schoolRepository, IUnitOfWork unitOfWork)
    {
        this._schoolRepository = schoolRepository;
        this._unitOfWork = unitOfWork;
    }
}
Run Code Online (Sandbox Code Playgroud)

容器配置

// Autofac iOC
        var builder = new ContainerBuilder();
        // register controllers
        builder.RegisterControllers(Assembly.GetExecutingAssembly());

        // register services
        builder.RegisterType<MembershipService>().As<IMembershipService>().InstancePerHttpRequest();
        builder.RegisterType<SchoolService>().As<ISchoolService>().InstancePerHttpRequest();
        builder.RegisterType<StudentService>().As<IStudentService>().InstancePerHttpRequest();
        builder.RegisterType<ClassRoomService>().As<IClassRoomService>().InstancePerHttpRequest(); …
Run Code Online (Sandbox Code Playgroud)

.net c# asp.net-mvc dependency-injection autofac

14
推荐指数
1
解决办法
1万
查看次数

在autofac中注册装饰器而无需手动指定所有依赖项

我有一个装饰器,有一些其他依赖项,也应该使用容器解决.例:

public class FooDecorator : IFoo
{
    public FooDecorator(IFoo inner, IBar bar, IBaz baz)
}
Run Code Online (Sandbox Code Playgroud)

我可以这样注册:

builder.RegisterType<Foo>().As<IFoo>();
builder.RegisterDecorator<IFoo>((c, inner) => 
    new FooDecorator(inner, c.Resolve<IBar>(), c.Resolve<IBaz>()), "key");
Run Code Online (Sandbox Code Playgroud)

这是有效的,但不是很好,我必须手动指定所有其他依赖项.我想做的是:

builder.RegisterDecorator<FooDecorator, IFoo>("key");
Run Code Online (Sandbox Code Playgroud)

IFoo其解析为'inner',IFoo并从容器中解析其他依赖项.这是可能的,还是我可以用Func注册装饰器会导致这种行为?

c# dependency-injection decorator autofac

14
推荐指数
2
解决办法
3458
查看次数

ASP.NET Web API跨请求缓存操作筛选器属性

在ASP.NET Web API(4.0.30506)中似乎有一些奇怪的行为,我以前没见过.

我所看到的是,相同的动作过滤器属性实例在Web API请求上重用.如果此属性将依赖项注入其中,这尤其是一个问题,因为这些依赖项可能特定于Web请求.我知道属性更好是被动的,但我的假设是动作过滤器属性没有被缓存.

我搜索了描述这个的任何文章,博客文章或微软更改日志及其背后的原因,但我找不到一件事.这让我想知道我的配置是否有问题导致这种情况发生.但是,我能够在一个新的,空的Visual Studio 2012 Web API项目中重现这个问题.

我所做的是使用带有"Web API"模板的Visual Studio 2012 ASP.NET MVC 4 Web应用程序项目创建一个新的空项目.它附带了Web API 4.0.20710.0 NuGet包.之后我添加了以下属性:

[DebuggerDisplay("{id}")]
public class TestFilterAttribute : System.Web.Http.Filters.ActionFilterAttribute {
    private static readonly List<int> used = new List<int>();

    private static int counter;
    private readonly int id;

    public TestFilterAttribute() {
        this.id = Interlocked.Increment(ref counter);
    }

    public override void OnActionExecuting(HttpActionContext actionContext) {
        // Just for testing: I would expect this line never to throw, but it does.
        if (used.Contains(this.id)) throw …
Run Code Online (Sandbox Code Playgroud)

.net c# asp.net dependency-injection asp.net-web-api

14
推荐指数
1
解决办法
3039
查看次数

如何在autofac中注册Generic接口的所有实现?

我创建了通用接口,假设映射实体以查看模型和向后.我必须在autofac配置中进行大约80次注册.是否可以将它们注册为批次?这是界面:

public interface ICommonMapper<TEntity, TModel, TKey>
    where TEntity : BaseEntity<TKey>
    where TModel : BaseEntityViewModel<TKey>
    where TKey : struct 
{
    TModel MapEntityToModel(TEntity entity);
    TModel MapEntityToModel(TEntity entity, TModel model);
    TEntity MapModelToEntity(TModel model);
    TEntity MapModelToEntity(TModel model, TEntity entity);
}
Run Code Online (Sandbox Code Playgroud)

谢谢!

c# interface autofac

14
推荐指数
2
解决办法
9621
查看次数

.NETStandard 1.0/.NET Core中Type.GetGenericArguments()的等价物是什么?

这个方法System.Type.GetGenericArguments()是从.NETStandard 1.0中"丢失"的,我认为它TypeInfo.GenericTypeArguments是替代品GetGenericArguments(),但不幸的是,它们在提供开放泛型类型时表现不同.以下面的代码为例:

Type type = typeof(ICommandHandler<>);
type.GetGenericArguments(); // return { TCommand }
type.GetTypeInfo().GenericTypeArguments; // returns empty array
Run Code Online (Sandbox Code Playgroud)

当该GetGenericArguments()方法返回泛型类型参数时TCommand,GenericTypeArguments只返回一个相同的open-generic类型的空数组.

.NET Standard 1.0 的确切行为GenericTypeArguments和等价物是Type.GetGenericArguments()什么?

.net c# .net-core .net-standard

14
推荐指数
1
解决办法
2074
查看次数

IoC:连接事件处理程序的依赖项

我正在构建一个WinForms应用程序,其UI只包含一个NotifyIcon动态填充的UI ContextMenuStrip.有一个MainForm共同持有的申请,但这是从来没有看见.

我开始尽可能安全地构建它(使用Autofac来处理对象图)并且对我的成功感到非常满意,即使使用O部分也相当不错.随着我目前正在实施的扩展,似乎我发现了我的设计中的一个缺陷,需要重新改造一下; 我想知道我需要去的方式但是有点不清楚如何准确定义依赖关系.

如上所述,菜单部分在启动应用程序后动态填充.为此,我定义了一个IToolStripPopulator接口:

public interface IToolStripPopulator
{
    System.Windows.Forms.ToolStrip PopulateToolStrip(System.Windows.Forms.ToolStrip toolstrip, EventHandler itemclick);
}
Run Code Online (Sandbox Code Playgroud)

将此实现注入到MainForm,并且Load()方法PopulateToolStrip()使用ContextMenuStrip表单中定义的处理程序调用.populator的依赖关系仅与获取用于菜单项的数据有关.

这个抽象通过一些进化步骤很好地工作,但是当我需要多个事件处理程序时,这已经不够了,例如因为我正在创建几个不同的菜单项组 - 仍然隐藏在单个IToolStripPopulator界面后面,因为表单不应该是完全关心这一点.

正如我所说,我想我知道一般结构应该是什么样的 - 我将IToolStripPopulator接口重命名为更具体的东西*并创建了一个新PopulateToolStrip()方法,其方法不接受EventHandler参数,而是将其注入到对象中(也允许更多关于实现所需的处理程序数量的更多灵活性等).这样,我的"最重要的" IToolStripPopulator可以很容易地成为任何数量的特定适配器的适配器.

现在我不清楚的是我应该如何解决EventHandler依赖项.我认为处理程序应该全部定义MainForm,因为它具有正确响应菜单事件所需的所有其他依赖项,并且它还"拥有"菜单.这意味着我IToolStripPopulator最终注入到MainForm中的MainForm对象的依赖关系需要依赖于对象本身Lazy<T>.

我的第一个想法是定义一个IClickHandlerSource接口:

public interface IClickHandlerSource
{
    EventHandler GetClickHandler();
}
Run Code Online (Sandbox Code Playgroud)

这是由我实现的MainForm,我的具体IToolStripPopulator实现依赖于Lazy<IClickHandlerSource>.虽然这有效,但它是不灵活的.我要么必须为可能越来越多的处理程序定义单独的接口(严重违反OCP与MainForm类)或不断扩展IClickHandlerSource(主要违反ISP).直接依赖事件处理程序在消费者方面看起来是一个好主意,但是通过惰性实例(或类似)的属性单独连接构造函数似乎非常混乱 - 如果可能的话.

我最好的打赌似乎是这样的: …

c# dependency-injection inversion-of-control winforms solid-principles

13
推荐指数
1
解决办法
2052
查看次数

在哪里验证命令的授权?

问题的标题重新开始:我在哪里验证命令的授权?

例如,将客户设置为首选包括:

  • MarkAsPreferred 控制器动作(可以是Winforms或其他);
  • SetCustomerAsPreferredCommand;
  • SetCustomerAsPreferredCommandHandler;
  • Customer.MarkAsPreferred() (域);

我确定了3个地方来检查授权:

  • 用于显示目的的UI(如果用户没有访问权限,用户不应该看到链接/按钮);
  • 控制器动作以验证用户是否有权调用该命令; 假设命令总是成功(关于验证,但我也假设授权),我们有机会告知用户缺乏访问权限;
  • 在调用域逻辑之前的命令内部 ;

SomeView.cshtml

if (authorizationService.Authorize("MarkCustomerAsPreferred))
{
    // show link
}
Run Code Online (Sandbox Code Playgroud)

CustomerController

[HttpPost]
public ActionResult MarkAsPreferred(Guid id)
{
    if (!authorizationService.Authorize("MarkCustomerAsPreferred))
    {
        return RedirectToAction("Unauthorized");
    }

    var MarkCustomerAsPreferredCommand { Id = id };
    ...
}
Run Code Online (Sandbox Code Playgroud)

MarkCustomerAsPreferredCommandHandler

public void Handle(MarkCustomerAsPreferredCommand command)
{
    if (!authorizationService.Authorize("MarkCustomerAsPreferred"))
    {
        throw new Exception("...");
    }

    customer.MarkAsPreferred();
}
Run Code Online (Sandbox Code Playgroud)

我的问题是:我是否需要在3个地方验证授权,或者我只是过度热心?

我搜索了整个互联网,但没有找到任何关于此的例子或参考.

编辑

经过更多研究和一些测试后,我认为包装命令以添加行为(授权,验证,日志记录),正如Dennis Taub所建议的那样,实施起来更容易,更清晰.

我发现这篇博文正好解释了这个概念.

关于为一个命令设置多个处理程序,我不需要为每个原始命令的每个行为实现一个命令处理程序,一个包装命令可以包装所有处理程序.

authorization cqrs

13
推荐指数
1
解决办法
2759
查看次数