我试图让Unity管理我的对象的创建,我希望有一些在运行时才知道的初始化参数:
目前,我能想到的方法是在接口上使用Init方法.
interface IMyIntf {
void Initialize(string runTimeParam);
string RunTimeParam { get; }
}
Run Code Online (Sandbox Code Playgroud)
然后使用它(在Unity中)我会这样做:
var IMyIntf = unityContainer.Resolve<IMyIntf>();
IMyIntf.Initialize("somevalue");
Run Code Online (Sandbox Code Playgroud)
在这种情况下,runTimeParamparam是在运行时根据用户输入确定的.这里的简单案例只返回值,runTimeParam但实际上参数将类似于文件名,初始化方法将对文件执行某些操作.
这会产生许多问题,即该Initialize方法在界面上可用并且可以多次调用.在实现中设置一个标志并在重复调用时抛出异常Initialize似乎很笨重.
在解析我的界面时,我不想知道有关实现的任何信息IMyIntf.但是,我想要的是知道这个接口需要一定的一次初始化参数.有没有办法以某种方式注释(属性?)具有此信息的接口,并在创建对象时将它们传递给框架?
编辑:更多地描述了界面.
interface-design dependency-injection ioc-container inversion-of-control unity-container
我决定开始使用Ninject并面临一个问题.说我有以下场景.我有一个IService接口和2个实现此接口的类.而且我还有一个类,它有一个构造函数获取IService和一个int.如何使用Ninject创建此类的实例(我不想硬连接这个int,我想在每次获取实例时都传递它)?
以下是一些说明情况的代码:
interface IService
{
void Func();
}
class StandardService : IService
{
public void Func()
{
Console.WriteLine("Standard");
}
}
class AlternativeService : IService
{
public void Func()
{
Console.WriteLine("Alternative");
}
}
class MyClass
{
public MyClass(IService service, int i)
{
this.service = service;
}
public void Func()
{
service.Func();
}
IService service = null;
}
class Program
{
static void Main(string[] args)
{
IKernel kernel = new StandardKernel(new InlineModule(
x => x.Bind<IService>().To<AlternativeService>(),
x => x.Bind<MyClass>().ToSelf())); …Run Code Online (Sandbox Code Playgroud) 它可能是之前被问过,但我甚至在官方网站上找不到为什么我应该使用MediatR以及它解决了什么问题?
是因为我可以在构造函数中传递单个对象而不是多个接口?
它是ServicesBus等的替代品还是竞争对手......
基本上有什么好处,它解决了什么问题
我想购买它,但我不清楚为什么我应该使用它.
非常感谢
弹簧有两种类型的DI:定位器DI和结构DI.
基于构造函数的DI修复了需要注入依赖项的顺序.基于Setter的DI不提供此功能.
基于Setter的DI帮助我们仅在需要时注入依赖项,而不是在构造时需要它.
我没有看到任何其他显着差异,因为两种类型的Spring DI都提供相同的功能 - 设置器和构造函数DI在代码启动时注入依赖关系.当然,构造函数DI将通过构造函数执行,而setter DI将在构造对象后立即通过setter执行它,但它在性能等方面对开发人员没有任何影响.两者都提供了指定顺序的方法依赖注入也是如此.
我正在寻找一个场景,其中一个提供明显优势,或一个类型完全无法使用.
我正在编写我的第二个真实应用程序,它使用DI.总的来说,我认为它有一个更好的设计.但是有一些代码味道,我不知道如何解决.
我更喜欢使用构造函数注入,并经常观察到我需要在构造函数中注入大约5个或更多对象.它似乎太多了,也许这是一个设计问题,没有让SRP正确.但我认为我对DI的使用也应该受到指责.
我正在寻找"最佳实践"或"经验法则",总的来说,我似乎注入了一切,那些不在.Net框架中,是否过度了?
为了开始,以下是我注入的两个对象示例,但我不确定.
像应用程序配置或那些小型util类这样的真正单例的对象是否会注入它们?它们似乎经常注入,注入它们的唯一原因似乎是允许改变测试的价值,但Ayende似乎以另一种方式解决了这个问题:http://ayende.com/Blog/archive/2008 /07/07/Dealing-with-time-in-tests.aspx.
几乎每个对象都使用的常见对象,如日志记录,是否应该注入?
我有一个A级,取决于其他10个类.根据依赖注入模式,我应该通过其构造函数传递A的所有依赖项.
所以我们假设这个构造函数(当然这不是一个工作或真实的代码,因为我不允许在这里发布真正的代码)
public ClassA(ClassB b, ClassC c, ClassD d, ClassE e, ClassF f, ClassG g, ClassH h, ClassI i) {
this.b = b;
this.c = c;
this.d = d;
this.e = e;
this.f = f;
this.g = g;
this.h = h;
this.i = i;
}
Run Code Online (Sandbox Code Playgroud)
我已经阅读了Martin Fowler关于重构的书,即有一个带有大量参数的方法是一种代码气味,不应该发生.
我的问题是:当我们谈论DI时,这样可以吗?是否有更好的方法可以在不违反Martin Fowler规则的情况下注入依赖关系?
我知道我可以通过属性传递依赖项,但这可能会导致错误,因为没有人真正确定应该传递什么才能使类工作.
编辑
谢谢你的所有答案.我现在将尝试演示一些A类依赖项:
1 - 访问数据库
2的类 - 访问另一个数据库的另一个类(是的,我需要在两个数据库上执行操作)
3 - 通过电子邮件发送错误通知的
类4 - 加载配置
的类5 - 一个类将作为某些操作的计时器(也许这可以避免)
6 - 具有业务逻辑的类
我试图摆脱任何其他许多其他人,但这些是非常必要的,我没有看到任何避免它们的方法.
编辑
经过一些重构后,我有7个依赖项(从10开始).但我有4个DAO对象:
CustomerDAO
ProcessDAO
ProductsDAO
CatalogDAO
是否正确创建另一个名为MyProjectDAO的类并将其注入其中?这样我只有一个DAO类聚合我项目的所有DAO对象.我不认为这是一个好主意,因为它违反了单一责任原则.我对吗?
如果这个问题已经讨论过,我很抱歉,但我并没有真正找到我想要的东西.我面临的问题更多是关于模式和设计选择而不是.NET本身.我想建议你知道从哪里开始我的重构.
今天我在我的实际应用程序中打开了一个类,发现它有13个由构造函数注入的依赖项!实际上,每个开发人员都在他正在编写的方法中添加了所需的依赖性.
我对DI的理解之一是,当我们通过构造函数注入依赖项时,它意味着它是一个强制依赖项,应该在类的所有方法中使用.如果我们只需要给定类的一个方法中的特定依赖项,它对您意味着什么?
找到合适的平衡点很困难.实际上,有时候不可能以干净的方式封装bahaviour.
我正在考虑创建像服务聚合器这样的东西来隐藏其中一个相关的依赖关系,但是如果你有其他建议的话.提前致谢.
问题:
假设班级:
public class MyAwesomeClass
{
private IDependCls _dependCls;
public MyAwesomeClass(IDependCls dependCls)
{
_dependCls = dependCls;
}
}
Run Code Online (Sandbox Code Playgroud)
在其他地方我需要获得该类的实例,如下所示:
public class SomewhereElse
{
public void AwesomeMethod()
{
//...
// AwesomeStuff
//...
var GetErDone = new MyAwesomeClass(); // PROBLEM! No constructor with 0 arguements
}
}
Run Code Online (Sandbox Code Playgroud)
问题是,我
建议的解决方案1:
A)必须制作一个额外的构造来解决依赖关系吗?例如:
public MyAwesomeClass() // new constructor
{
_dependCls = DependencyResolver.Current.GetService<IDependCls>();
}
public class SomewhereElse
{
public void AwesomeMethod()
{
var GetErDone = new MyAwesomeClass(); // IT WORKS!!
}
}
Run Code Online (Sandbox Code Playgroud)
建议的解决方案2:
B)使用AwesomeMethod之前 …
c# asp.net-mvc dependency-injection inversion-of-control autofac
我在DI IOC的Web项目中使用StructureMap.它工作得很完美,但我不知道如何用StructureMap编写单元测试.
我应该在AssemblyInitialize中开始配置StructureMap,就像在global.asax中一样,除了datacontext不使用实时LinqToSqlDataContext但是有些内存数据如下:
[AssemblyInitialize]
public static void Start()
{
ObjectFactory.Configure(x =>
{
x.For<IDataContext>().HttpContextScoped().Use<MemoryDataContext>()
.Ctor<string>("connectionString")
.Is(ConfigurationManager.ConnectionStrings["DEVConnection"].ConnectionString);
x.For<IDepartamentRepository>().Use<DepartamentDB>();
x.For<IDevelopmentProcess>().Use<DevelopmentProcesses>().OnCreation(c => c.User = Current.CurrentUser);
x.For<IActivityProcess>().Use<ActivitiesProcess>().OnCreation(c=> c.User = Current.CurrentUser);
x.For<IDevDeveloperRepository>().Use<DevDeveloperDB>();
x.For<IDevelopmentRepository>().Use<DevelopmentDB>();
x.For<IActivityRepository>().Use<ActivityDB>();
x.For<IActivityTypeRepository>().Use<ActivityTypeDB>();
x.For<IDevUserRepository>().Use<DevUsersDB>();
x.For<IAttachmentRepository>().Use<AttachmentDB>();
}
);
}
Run Code Online (Sandbox Code Playgroud)
然后使用ObjectFactory.GetInstance()测试或我该怎么做?
c# ×5
asp.net ×1
asp.net-mvc ×1
autofac ×1
ninject ×1
refactoring ×1
spring ×1
structuremap ×1
unit-testing ×1