Autofac有模块,Windsor有安装程序和StructureMap注册表...使用Simple Injector如何将配置逻辑打包成可重用的类?
我试过了:
public interface IModule { }
public class FooModule : IModule
{
public FooModule(SimpleInjector.Container container)
{
container.RegisterSingleton<IBar, Bar>();
container.RegisterSingleton<IFoo, Foo>();
}
}
Run Code Online (Sandbox Code Playgroud)
我在Composition Root中使用它:
public static void Main(string[] args)
{
var container = new SimpleInjector.Container();
container.RegisterCollection<IModule>(new FooModule(container));
...
}
Run Code Online (Sandbox Code Playgroud)
但是,FooModule取决于容器,可能不是一个好的做法...请参阅http://code.google.com/p/autofac/wiki/BestPractices:
如果组件依赖于容器,请查看它们如何使用容器来检索服务,并将这些服务添加到组件(依赖注入)构造函数参数中.
我们正在重新设计一些遗留软件以使其更易于测试,并决定使用Dependency-Injection和Castle.Windsor来帮助我们.
首先,我们的目标:*许多装饰器都在数据流上工作.*装饰器的多种组合是可能的,并且每种情况下的根节点可能需要从不同的位置获取数据.
从技术上讲,我们的设计如下:
interface IUpdateableValue<T>
{
T Get();
};
Run Code Online (Sandbox Code Playgroud)
我们有三组要检索的数据,包含许多组件,都实现了IUpdateableValue()(伪代码):
JsonParser(
Decompressor(
Decrypter(decryptionKey
FileCache(filename,
HttpWebDownloader(url))))
XmlParser(
Decompressor(
Decrypter(decryptionKey2
FileCache(filename2,
HttpWebDownloader(url2))))
Run Code Online (Sandbox Code Playgroud)
我无法将设计融入像Castle-Windsor这样的DI框架中.我怀疑其中一些可以由命名实例处理,但这对于这种用法来说似乎很臭.
这个想法是,例如JsonParser和XmlParser实例的"用户"不知道(或关心)数据是来自HttpUrl,文件还是神奇地从帽子中拉出来的.
我在想我们的设计有问题,但不确定如何修复它.
关于如何进步的任何想法?
我正在构建一个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
相比AppDomain.GetAssemblies(),BuildManager.GetReferencedAssemblies()(System.Web.Compilation.BuildManager)似乎是一种更可靠的方式来获得由在运行ASP.NET应用程序中引用的程序集,因为AppDomain.GetAssemblies()只得到"已经将组件已经被加载到此应用程序域的执行上下文".
迭代所有程序集是在DI容器中应用程序启动时动态注册类型的重要工具,特别是在应用程序启动期间,可能还有其他程序集未加载(不需要),组合根是第一个需要它们的人.因此,有一个可靠的方法来获取应用程序的引用程序集非常重要.
虽然BuildManager.GetReferencedAssemblies()对于ASP.NET应用程序来说是一种可靠的方法,但我想知道:有哪些替代方案可用于其他类型的应用程序,例如桌面应用程序,Windows服务和自托管WCF服务?
这篇MSDN文章描述了如何在ASP.NET Web API中有效地使用HTTP消息处理程序来"装饰"请求.此外,本文还显示了以下代码,用于将自定义处理程序注册到Web API管道中:
config.MessageHandlers.Add(new MessageHandler1());
Run Code Online (Sandbox Code Playgroud)
我对这种方法的问题在于它将MessageHandler1有效地注册为单例.当处理程序本身没有状态且没有依赖关系时,这很好,但在基于SOLID设计原则的系统中,这些处理程序很可能具有自己的依赖关系,并且很可能这些依赖关系需要一个寿命短于单身人士.
如果是这种情况,则不应将此类消息处理程序创建为单例,因为通常,组件的生命周期永远不会超过其依赖项的生存期.
所以我的问题是,我们有什么替代方法来注册自定义消息处理程序,以便可以在每个请求中从IoC容器中解析它们?
c# asp.net dependency-injection inversion-of-control asp.net-web-api
所以我在x/y坐标系对我有意义的其他平台上开发了游戏.左上角表示坐标为(0,0)且右下角为(宽度,高度)的游戏画面.现在我正试图跳转到Unity 2d,我无法理解游戏画面是如何工作的.如果我在屏幕上有一个背景对象和一个角色对象,当我移动角色时,他的x和y值会在-3和3之间变化...非常小的坐标,它与我设置的游戏分辨率不匹配( 1024×768).有没有很好的教程来理解Unity中的游戏网格?或者任何人都可以解释我如何能够完成我想要做的事情?
按照我在这个线程中给出的建议[ Ninject UOW模式,用户通过身份验证后的新ConnectionString我现在明白我不应该使用以下行...
var applicationConfiguration =
(IApplicationConfiguration)
DependencyResolver.Current.GetService(typeof(IApplicationConfiguration));
Run Code Online (Sandbox Code Playgroud)
......作为服务定位器是一种反模式.
但是在以下过程的情况下,如何实例化实现" IApplicationConfiguration "的具体对象,以便我可以使用该对象获取未知用户角色名称,或者使用它来分配我的原则的" ApplicationConfiguration "属性?
Global.asax中
public class MvcApplication : NinjectHttpApplication
{
/// <summary>
/// Handles the PostAuthenticateRequest event of the Application control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
protected void Application_PostAuthenticateRequest(Object sender, EventArgs e)
{
String[] roles;
var applicationConfiguration =
(IApplicationConfiguration)
DependencyResolver.Current.GetService(typeof(IApplicationConfiguration));
var identity = HttpContext.Current.User.Identity;
if (Request.IsAuthenticated)
{
roles = Roles.GetRolesForUser(identity.Name);
}
else
{
roles …Run Code Online (Sandbox Code Playgroud) c# dependency-injection anti-patterns ninject service-locator
我正在使用Owin,Web API,实体框架,ASP.NET身份创建API.我使用Simple Injector作为我选择的DI框架.
在Owin启动过程中,我想用一些示例数据为我的数据库设定种子.这由一个实现类处理IDatabaseInitializer,看起来像这样:
public class MyDbInitializer : DropCreateDatabaseAlways<MyDataContext>
{
private readonly IUserManager _userManager;
public MyDbInitializer(IUserManager userManager)
{
_userManager = userManager;
}
protected override void Seed(MyDataContext context)
{
SeedIdentities();
}
private void SeedIdentities()
{
var user = new User
{
UserName = "someUsername",
Email = "some@email.com"
};
_userManager.CreateAsync(user, "Password");
}
Run Code Online (Sandbox Code Playgroud)
IUserManager是ASP.NET Identiy UserManager类的代理,它间接依赖于IUnitOfWork.如果你想知道,IUserManager注册如下:
container.Register(typeof(IUserManager),
() => container.GetInstance<IUserManagerFactory>().Create());
Run Code Online (Sandbox Code Playgroud)
因为我想根据Web API请求使用单个工作单元,所以我已经注册了IUnitOfWork以下内容:
container.RegisterWebApiRequest<IUnitOfWork, MyUnitOfWork>();
Run Code Online (Sandbox Code Playgroud)
除了解析类中的IUserManager依赖项之外,这对于所有事情都很好MyDbInitializer.在应用程序启动期间,SimpleInjector失败并出现以下ActivationException:
SimpleInjector.ActivationException was …Run Code Online (Sandbox Code Playgroud) c# dependency-injection simple-injector asp.net-web-api owin
我刚刚安装了新版本的Visual Studio 2015社区版(RTM),我试图让我的开源项目在VS2015和C#6.0下运行.
我的一些.cs在项目中共享.这样我就可以构建PCL版本(功能有限)和核心库的"完整"版本.
但是出于某种原因,某些代码文件在整个项目中正确构建,但在PCL项目中构建时会失败(其中所有内容都在C#5和Visual Studio 2013下编译).cref在构建PCL版本时,编译器似乎无法解析XML注释.这是一个在我的机器上失败的简化代码示例:
/// <summary></summary>
public class A
{
// Compile error on next line:
/// <summary><see cref="Y(Type)"/>.</summary>
public void X() { }
/// <summary></summary>
/// <param name="x"></param>
public void Y(Type x) { }
/// <summary></summary>
/// <param name="i"></param>
public void Y(int i) { }
}
Run Code Online (Sandbox Code Playgroud)
我得到的编译错误是:
CS1580参数的类型无效XML注释cref属性中的类型:'Y(Type)'SimpleInjector.PCL
奇怪的是,XML评论中的IntelliSense支持(哇!我们现在在XML评论中有智能感知!)实际上是可行的,并且该方法Y(Type)可以通过下拉列表进行选择.但选择此选项后,将生成编译错误(仅在PCL中).
我的问题当然是如何解决这个问题?这是个常见的问题吗?项目的配置可能与此有关吗?这是一个已知的错误?
我注意到在一些.net核心示例中有调用 TryAddSingleton,有些是 AddSingleton在注册服务时.
如果服务类型尚未注册,则反编译器会显示TryAdd(由TryAddSingleton调用)将指定的参数"descriptor"添加到"集合".
这是否意味着使用TryAddSingleton总是更安全,以防某些其他方法/库已经注册了同一个类?
c# ×8
.net ×2
asp.net ×2
winforms ×2
2d ×1
asp.net-core ×1
asp.net-mvc ×1
c#-6.0 ×1
game-engine ×1
ninject ×1
owin ×1
startup ×1
wcf ×1