我刚刚开始使用微软的Unity应用程序块依赖注入库,而且我已经失败了.
这是我的IoC类,它将处理我的具体类到它们的接口类型的实例化(所以每次我在控制器中需要一个存储库时,我不必在IoC容器上保持名为Resolve):
public class IoC
{
public static void Intialise(UnityConfigurationSection section, string connectionString)
{
_connectionString = connectionString;
_container = new UnityContainer();
section.Configure(_container);
}
private static IUnityContainer _container;
private static string _connectionString;
public static IMovementRepository MovementRepository
{
get { return _container.Resolve<IMovementRepository>(); }
}
}
Run Code Online (Sandbox Code Playgroud)
所以,我的想法是,从我的控制器,我可以做到以下几点:
_repository = IoC.MovementRepository;
Run Code Online (Sandbox Code Playgroud)
我目前收到错误:
异常是:InvalidOperationException - 无法构造String类型.您必须配置容器以提供此值.
现在,我假设这是因为我的映射具体实现需要为其构造函数提供单个字符串参数.具体课程如下:
public sealed class MovementRepository : Repository, IMovementRepository
{
public MovementRepository(string connectionString) : base(connectionString) { }
}
Run Code Online (Sandbox Code Playgroud)
其中继承自:
public abstract class Repository
{
public Repository(string connectionString)
{
_connectionString = …Run Code Online (Sandbox Code Playgroud) c# dependency-injection inversion-of-control unity-container repository-pattern
我使用Unity成功为所有常规构造注射,如仓库等,但我不能让它与ASP.NET身份类的工作.设置是这样的:
public class AccountController : ApiController
{
private UserManager<ApplicationUser> _userManager { get; set; }
public AccountController(UserManager<ApplicationUser> userManager)
{
if (userManager == null) { throw new ArgumentNullException("userManager"); }
_userManager = userManager;
}
// ...
}
Run Code Online (Sandbox Code Playgroud)
使用Unity的这些配置:
unity.RegisterType<AccountController>();
unity.RegisterType<UserManager<ApplicationUser>>(new HierarchicalLifetimeManager());
unity.RegisterType<IUserStore<ApplicationUser>, UserStore<ApplicationUser>>(new HierarchicalLifetimeManager());
Run Code Online (Sandbox Code Playgroud)
这与Autofac,Ninject的其他帖子相同,例如,但在我的情况下它不起作用.错误消息是:
尝试创建"AccountController"类型的控制器时发生错误.确保控制器具有无参数的公共构造函数.手动创作当然是:
public AccountController()
: this(new UserManager<ApplicationUser>(new UserStore<ApplicationUser>("Mongo")))
{
}
Run Code Online (Sandbox Code Playgroud)
怎么了?
UPDATE
正如@emodendroket所建议的,缩短代码就可以了.不需要Unity.Mvc包.
unity.RegisterType<IUserStore<IdentityUser>,
MyCustomUserStore>(new HierarchicalLifetimeManager());
Run Code Online (Sandbox Code Playgroud)
和
public AccountController(UserManager<IdentityUser> _userManager,
IAccountRepository _account)
{
// ...
Run Code Online (Sandbox Code Playgroud) c# asp.net dependency-injection unity-container asp.net-identity
采取以下无用的计划:
class Program
{
static void Main(string[] args)
{
IUnityContainer unityContainer = new UnityContainer();
IWindsorContainer windsorContainer = new WindsorContainer();
Program unityProgram = unityContainer.Resolve<Program>();
Program castleProgram = windsorContainer.Resolve<Program>();
}
}
Run Code Online (Sandbox Code Playgroud)
UnityContainer将返回一个Program实例,其中Windsor容器将抛出ComponentNotFoundException.
我可以看到这两种行为的争论,并且不介意我最终会遇到什么,但是Prism V2 Drop 8(写作时最新的)依赖于内部的Unity行为,请求尚未注册的类.
而不是为Prism找到并注册所有这些类,我宁愿让Windsor表现得像Unity一样.我没有在谷歌找到任何帮助我这样做的东西(虽然我的术语可能是错的)和Windsor文档相当糟糕...
任何人都可以建议解决这个问题吗?
(来自Prism V2 StockTrader示例应用程序中的StockTraderRIBootstrapper.cs文件)
这有什么区别:
ShellPresenter presenter = new ShellPresenter();
Run Code Online (Sandbox Code Playgroud)
还有这个:
ShellPresenter presenter = Container.Resolve<ShellPresenter>();
Run Code Online (Sandbox Code Playgroud)
这样的事情:
Container.RegisterType<IShellPresenter, ShellPresenter>();
Run Code Online (Sandbox Code Playgroud)
但发现它无处可寻.那么容器如何才能了解这些类型呢?它们可以解决它们吗?我在自己的项目中重建了这个并获得"依赖失败的解决方案"错误,那么我在哪里需要注册这个依赖呢?
这里的任何方向/讨论都会有所帮助.
所以,在bootstrapper中,当我注册Shell本身时:
protected override void ConfigureContainer()
{
Container.RegisterType<IShellView, Shell>();
base.ConfigureContainer();
}
Run Code Online (Sandbox Code Playgroud)
然后Container可以解析ShellPresenter类型.那么当我注册Shell类型时,ShellPresenter类型是如何注册的?
好的,所以事实证明你不必注册你想要解决的类型,但你必须注册传递给你想要解决的类型的构造函数的参数(接口)类型,即因为我注入IShellView接口进入我的ShellPresenter的构造函数,我需要注册IShellView类型而不是IShellPresenter类型:
public ShellPresenter(IShellView view) ...
Run Code Online (Sandbox Code Playgroud)
我通过尝试解决类型测试器测试了这个:
Tester tester = Container.Resolve<Tester>();
Run Code Online (Sandbox Code Playgroud)
只要我将SomeClass注入其构造函数:
public Tester(ISomeClass someClass)
Run Code Online (Sandbox Code Playgroud)
在我用容器注册SomeClass之前,我得到了未解决的依赖错误:
Container.RegisterType<ISomeClass, SomeClass>();
Run Code Online (Sandbox Code Playgroud)
然后它工作.这和教育一样令人惊讶.需要沉入其中.我要去喝杯咖啡并考虑一下.
如果有人能详细说明为什么会这样,那将非常感激.
我正在考虑使用Unity来管理自定义用户类实例的生命周期.我计划使用自定义ASP.NET会话管理器扩展LifetimeManager.我希望能够做的是从我的自定义类存储和检索当前登录的用户对象,并让Unity从ASP.NET中的会话对象获取User的实例,或者(在Win32项目中时)检索它静态地或从当前线程.
到目前为止,我最好的解决方案是在启动时创建Unity容器的静态实例,并使用Resolve方法从我的每个类中获取我的User对象.但是,这似乎在我的其他类中创建了对unity容器的依赖.实现这一目标的"团结"方式是什么?我希望能够从任何类中读取/替换当前的User实例.
我正在试图找出一个正确的方法来注入一个需要参数的自动工厂,或者即使这可以通过Unity实现.
例如,我知道我可以这样做:
public class TestLog
{
private Func<ILog> logFactory;
public TestLog(Func<ILog> logFactory)
{
this.logFactory = logFactory;
}
public ILog CreateLog()
{
return logFactory();
}
}
Container.RegisterType<ILog, Log>();
TestLog test = Container.Resolve<TestLog>();
ILog log = test.CreateLog();
Run Code Online (Sandbox Code Playgroud)
现在我希望能做的是:
public class TestLog
{
private Func<string, ILog> logFactory;
public TestLog(Func<string, ILog> logFactory)
{
this.logFactory = logFactory;
}
public ILog CreateLog(string name)
{
return logFactory(name);
}
}
Container.RegisterType<ILog, Log>();
TestLog test = Container.Resolve<TestLog>();
ILog log = test.CreateLog("Test Name");
Run Code Online (Sandbox Code Playgroud)
不幸的是,这不起作用.我可以看到你如何设置自定义工厂来在Unity中创建实例,似乎无法为这个例子提供任何明确的例子.
显然我可以创建自己的工厂,但我正在寻找一种优雅的方式在Unity中以最少的代码执行此操作.
我有一个带有可选依赖项的存储库类:
class MyRepository : BaseRepository, IMyRepository
{
public MyRepository(IDataContext dataContext, ICacheProvider cacheProvider = null)
: base(dataContext, cacheProvider)
{}
// …
}
Run Code Online (Sandbox Code Playgroud)
cacheProvider参数的存在充当存储库的策略.我想要像这样设置Unity容器:
Container.RegisterType<IDataContext, MyDataContext>(new PerResolveLifetimeManager(), new InjectionConstructor())
.RegisterInstance<ICacheProvider>(null) // ???
.RegisterType<IMyRepository, MyRepository>();
Run Code Online (Sandbox Code Playgroud)
即没有为MyRepository指出具有一个参数的特定InjectionConstructor,而是使用带有null的默认构造函数作为cacheProvider参数.
有没有办法做到这一点?
我想做一个简单的多种类型注册解决方案(最终注入构造函数,但使用.Resolve来查看Unity是否能够执行此类操作.
在下面的每种情况下,Unity都会解析0应该解决的项目2.
是否有一些团结的转变可以打开2007年后的行为?还是我只是大失所想?
这是我的代码:
public interface IFoo {}
public class Foo1 : IFoo{}
public class Foo2 : IFoo{}
class Program
{
static void Main(string[] args)
{
var container = new UnityContainer();
container.RegisterType<IFoo, Foo1>();
container.RegisterType<IFoo, Foo2>();
// container.Resolve<IEnumerable<IFoo>>(); returns 0
// container.ResolveAll<IFoo>(); returns 0
var foos = container.Resolve<IFoo[]>();
Console.WriteLine(foos.Count());
Console.ReadLine();
}
}
Run Code Online (Sandbox Code Playgroud) 这是我的dad班级
public class Dad
{
public string Name
{
get;set;
}
public Dad(string name)
{
Name = name;
}
}
Run Code Online (Sandbox Code Playgroud)
这是我的测试方法
public void TestDad()
{
UnityContainer DadContainer= new UnityContainer();
Dad newdad = DadContainer.Resolve<Dad>();
newdad.Name = "chris";
Assert.AreEqual(newdad.Name,"chris");
}
Run Code Online (Sandbox Code Playgroud)
这是我得到的错误
"InvalidOperationException - the type String cannot be constructed.
You must configure the container to supply this value"
Run Code Online (Sandbox Code Playgroud)
如何配置我DadContainer的断言传递?谢谢
c# dependency-injection inversion-of-control unity-container visual-studio-2010
我需要一种方法来存储每个请求的日志对象.使用HttpContext,我会将其添加到项目Dictionary中.如果我能帮助它,我不想把HttpContext带进去.下面的代码是我为Unity LifeTimeManager提出的建议,它将在OwinContext的Environment属性中存储对象,我可以使用我的Owin中间件访问它.
public class OwinContextLifetimeManager : LifetimeManager
{
private string key = (new Guid()).ToString();
private IDictionary<string, object> environment;
public OwinContextLifetimeManager(IDictionary<string, object> environment)
{
this.environment = environment;
}
public override object GetValue()
{
if (environment != null && environment.ContainsKey(key))
return environment[key];
else
return null;
}
public override void RemoveValue()
{
if (environment != null)
environment.Remove(key);
}
public override void SetValue(object newValue)
{
if (environment != null)
environment[key] = newValue;
}
}
Run Code Online (Sandbox Code Playgroud)
然后我可以从我的中间件中使用它:
container.RegisterType<IRequestLog, RequestLog>(new OwinContextLifetimeManager(environment));
Run Code Online (Sandbox Code Playgroud)
在我看来,我可以选择我想要的任何键,除了那些已经由Owin保留的键.有什么理由我不应该为此目的使用OwinContext.Environment吗?MSDN文档对此的最佳实践含糊不清.
Darrel Miller在这里的回答:当使用OWIN自我主机时,我应该如何存储每个请求数据ASP.NET Web API …