我正在将大量代码移到Castle Trunk中,其中包括用于配置容器的新流畅界面.由于该项目有一个超出维护的巨大windsorConfig xml文件,我想我会开始利用这个新功能.我知道其他容器(例如StructureMap 2.0)也包含用于容器配置的流畅接口,所以这个问题不是基于Windsor.
我的问题是你使用新的流畅样式接口用于容器配置的约定/习语/模式是什么?
我的第一个想法是在某处创建一个静态方法(例如ContainerConfig.Config),它会将应用程序使用的所有相关类型加载到容器中.我担心最终这个单片函数最终会像xml配置文件一样难以维护(减去尖括号税).
我的第二个想法是将其分解,因此每个依赖程序集按照惯例导出其默认配置.我可以看到这对程序集内部使用的层次结构很有用.但对于外部使用的类型,是否应该在内部定义配置?
我想的越多,我似乎提出的问题就越多.你对此有什么想法?
我已经实现了我自己的模型视图演示者模式的副本(在Web客户端软件工厂的静脉中),所以我可以利用我自己的DI框架而不是绑定到WCSF的ObjectBuilder,我遇到了很多问题.我想出了几个方法来做到这一点,但没有一个特别让我开心.我想知道是否有其他人有其他想法.
使用HttpModule拦截context.PreRequestHandlerExecute来调用ObjectFactory.BuildUp(HttpContext.Current.Handler)
public partial class _Default : Page, IEmployeeView
{
private EmployeePresenter _presenter;
private EmployeePresenter Presenter
{
set
{
_presenter = value;
_presenter.View = this;
}
}
}
Run Code Online (Sandbox Code Playgroud)
在页面加载中调用buildup而不是使用HttpModule
public partial class _Default : Page, IEmployeeView
{
private EmployeePresenter _presenter;
private EmployeePresenter Presenter
{
set
{
_presenter = value;
_presenter.View = this;
}
}
protected void Page_Load(object sender, EventArgs e)
{
ObjectFactory.BuildUp(this);
}
}
Run Code Online (Sandbox Code Playgroud)
如果需要,通过Property访问presenter允许Getter to BuildUp.
public partial class _Default : Page, IEmployeeView
{
private EmployeePresenter …Run Code Online (Sandbox Code Playgroud) 如何在StructureMap Registy构造函数中获取某种类型的实例(在不同的注册表中注册)?我想使用这样的代码:
public RepositoriesRegistry()
{
IApplicationSettings lApplicationSettings =
ObjectFactory.GetInstance<IApplicationSettings>();
Debug.Assert(lApplicationSettings != null);
const string cSupportedDevicesConnectionString =
"metadata=res://*/Models.SupportedDevices.Database.SupportedDevicesModel.csdl|res://*/Models.SupportedDevices.Database.SupportedDevicesModel.ssdl|res://*/Models.SupportedDevices.Database.SupportedDevicesModel.msl;provider=System.Data.SqlClient;provider connection string=\"{0}\"";
string lSupportedDevicesConnectionString =
string.Format(cSupportedDevicesConnectionString, lDatabaseConnectionString);
SupportedDevicesEntities lSupportedDevicesEntities =
new SupportedDevicesEntities(lSupportedDevicesConnectionString);
ForRequestedType<SupportedDevicesEntities>().TheDefault.IsThis(
lSupportedDevicesEntities);
ForRequestedType<ISupportedDevicesRepository>().TheDefault.IsThis(
new SupportedDevicesRepository(lSupportedDevicesEntities));
}
Run Code Online (Sandbox Code Playgroud)
IApplicationSettings是应用程序设置的接口.实现此接口的具体类型(当前为ConfigFileApplicationSettings类)在另一个注册表中注册,如下所示:
public ApplicationServicesRegistry()
{
ForRequestedType<IApplicationSettings>().TheDefault.IsThis(
new ConfigFileApplicationSettings());
}
Run Code Online (Sandbox Code Playgroud)
这两个注册表都在Bootstrapper中注册:
#region IBootstrapper Members
public void BootstrapStructureMap()
{
ObjectFactory.Initialize(InitalizeStructureMapContainer);
}
#endregion
#region Private properties
private static bool HasStarted { get; set; }
#endregion
#region Private methods
private void InitalizeStructureMapContainer(IInitializationExpression x)
{
x.IgnoreStructureMapConfig = true;
x.AddRegistry<ViewModelRegistry>();
x.AddRegistry<ApplicationServicesRegistry>();
x.AddRegistry<RepositoriesRegistry>(); …Run Code Online (Sandbox Code Playgroud) 我有一个通用的IRepository,它有2个构造函数,一个没有参数,另一个有datacontext作为参数.我想在这种情况下使用无参数构造函数将结构图定义为远离.我想要一种方法来创建一个无参数的构造函数,我见过的其他解决方案,他们创建一个新的Datacontext并将其传递给具有参数的构造函数.
structuremap generics asp.net-mvc dependency-injection ioc-container
使用Factory方法检索注入的对象是不错的做法,还是只使用DI框架中的工厂方法?
我正在使用结构图,我应该只使用ObjectFactory.GetInstance();还是应该创建工厂类并在此类中调用ObjectFactory.GetInstance();? 因为如果我调用ObjectFactory.GetInstance(); 在我的课程中,我将创建与DI框架的耦合?抱歉,如果我无知,我对这个概念不熟悉.谢谢!
在创建Controller1时,我希望IService将映射到ConcreteService1,将IPageService映射到ConcretePageService1
当创建Controller2时,我希望IService将映射到ConcreteService2,IPageService将映射到ConcretePageService2
我如何初始化ObjectFactory以便以上工作?
这意味着我以这种方式初始化ObjectFactory:
ObjectFactory.Initialize(x =>
{
x.For<IService>().Use<ConcreteService1>();
x.For<IPageService>().Use<ConcretePageService1>();
});
Run Code Online (Sandbox Code Playgroud)
但是,这始终映射ConcreteService1到IService和ConcretePageService1到IPageService无论控制器类型
public class Controller1 : Controller
{
public Controller1(IService service, IPageService pageService)
{
}
}
public class Controller2 : Controller
{
public Controller2(IService service, IPageService pageService)
{
}
}
public interface IService
{
}
public class ConcreteService1:IService
{
}
public class ConcreteService2:IService
{
}
public interface IPageService
{
}
public class ConcretePageService1:IPageService
{
}
public class ConcretePageService2:IPageService
{
}
Run Code Online (Sandbox Code Playgroud) 在StructureMap 2中我有这样的事情:
For<ILogger>().HybridHttpOrThreadLocalScoped().Use<Logger>();
Run Code Online (Sandbox Code Playgroud)
使用Structure Map 3时,我应该使用以下内容吗?
For<ILogger>().LifecycleIs<HybridLifecycle>().Use<Logger>();
Run Code Online (Sandbox Code Playgroud)
然后我尝试将相同的更改应用于:
For<IDispatcher>().Transient().Use<Dispatcher>();
Run Code Online (Sandbox Code Playgroud)
我无法使用:
For<IDispatcher>().LifecycleIs<Transient>().Use<Dispatcher>();
Run Code Online (Sandbox Code Playgroud)
为什么?
谢谢你,米格尔
我尝试装饰IProjectService但我找不到struturemap的文档
For<IProjectService>().Use<ProjectServiceLogDecorator>();
For<IProjectService>().Use<ProjectService>()
.DecorateWith((context, decorator) =>
context.GetInstance<ProjectServiceLogDecorator>());
Run Code Online (Sandbox Code Playgroud)
我做错了什么?
exeption:
检测到双向依赖关系!检查以下StructureMap堆栈跟踪:1.)新ProjectServiceLogDecorator(IRepository的默认,IUnitOfWork的默认,IProjectService的默认,的IPrincipal的默认,AuditEventLogger的默认)2.)3. Project.Services.Projects.ProjectServiceLogDecorator)实例Project.Services的.Projects.ProjectServiceLogDecorator 4.)Project.Services.Projects.IProjectService的FuncInterceptor:IContext.GetInstance()5.)Project.Services.Projects.ProjectService 6.)Project.Services.Projects.IProjectService的实例(Project.Services.Projects) .ProjectService)7.)新的UsersController(IUserService的默认值,IService的默认,IUserNotificationService的默认, IService的默认,IProjectService的默认,ILicenseGroupService的默认)8.)Project.Web.Api.Controllers.UsersController 9.)Project.Web.Api.Controllers.UsersController 10的实例)的容器.GetInstance(Project.Web.Api.Controllers.UsersController)
我找到了解决办法,但令人作呕的是:
For<IProjectService>().Use<ProjectService>().DecorateWith((ctx, service) =>
new ProjectServiceLogDecorator(
ctx.GetInstance<IRepository<Project>>(),
ctx.GetInstance<IUnitOfWork>(),
service,
ctx.GetInstance<ILicenseService>(),
ctx.GetInstance<IPrincipal>(),
ctx.GetInstance<AuditEventLogger>()
)
);
Run Code Online (Sandbox Code Playgroud) 我有一个使用多个数据库分片的API应用程序,使用StructureMap进行依赖注入.每个API调用中所需的标头之一是a ShardKey,它告诉我此调用正在寻址的数据库.为了实现这一点,我有一个OwinMiddleware名为的类ShardingMiddleware,其中包含以下代码(为清晰起见,已剪切):
var nestedContainer = container.GetNestedContainer();
using (var db = MyDbContext.ForShard(shardKey)) // creates a new MyDbContext with connection string appropriate to shardKey
{
nestedContainer.Configure(cfg => cfg.For<MyDbContext>().Use(db));
await Next.Invoke(context);
}
Run Code Online (Sandbox Code Playgroud)
这在我的测试环境中运行良好,并通过了一系列集成测试.
但是集成测试实际上是单线程的.当我将其部署到QA环境中时,真正的应用程序通过多个同时呼叫击中我的API,事情开始变得梨形.Ferinstance:
System.ObjectDisposedException:无法访问已处置的对象.此错误的常见原因是处理从依赖项注入解析的上下文,然后尝试在应用程序的其他位置使用相同的上下文实例.如果您在上下文中调用Dispose()或将上下文包装在using语句中,则可能会发生这种情况.如果使用依赖项注入,则应该让依赖项注入容器负责处理上下文实例.
或者其他异常表明StructureMap没有MyDbContext可用的有效实例.
对我来说,似乎多个线程在某种程度上混淆了彼此的配置,但对于我的生活,我无法理解如何,因为我正在使用嵌套容器来存储每个API调用的数据库上下文.
有什么想法可能会出错吗?
更新:我还尝试将我的Db上下文抽象为一个接口.没有真正的区别; 我仍然得到错误
System.InvalidOperationException:尝试创建"SomeController"类型的控制器时发生错误.确保控制器具有无参数的公共构造函数.---> StructureMap.StructureMapConfigurationException:没有注册默认实例,无法自动确定类型'MyNamespace.IMyDbContext'
更新2:我解决了问题,但赏金仍然是开放的.请参阅下面的答案.
有很多文章讨论如何使用ASP.NET Core的Structure Map,但谈论控制台应用程序或Windows服务并不是很多.ASP.Net Core中的默认行为是StructureMap为每个HTTPRequest创建一个嵌套容器,以便每个HTTP请求只对实例化一个具体类.
我正在使用PeterKottas.DotNetCore.WindowsService nuget包创建.Net核心Windows服务.我使用这篇文章设置了StructureMap:https://andrewlock.net/using-dependency-injection-in-a-net-core-console-application/
我的Windows服务是在Timer上设置的,每X秒执行一次动作.我希望这些操作中的每一个都使用类似于ASP.NET的嵌套容器.换句话说,我希望在轮询传递完成后处理为轮询传递#1创建的所有内容.当轮询#2开始时,我想要实例化所有对象的新实例.但是,在单个轮询传递的范围内,我只希望创建每个对象的一个实例.
这样做的正确方法是什么?
这是我的程序类
public class Program
{
public static ILoggerFactory LoggerFactory;
public static IConfigurationRoot Configuration;
static void Main(string[] args)
{
var applicationBaseDirectory = AppContext.BaseDirectory;
string environment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
if (string.IsNullOrWhiteSpace(environment))
throw new ArgumentNullException("Environment not found in ASPNETCORE_ENVIRONMENT");
ConfigureApplication(applicationBaseDirectory, environment);
var serviceCollection = ConfigureServices();
var serviceProvider = ConfigureIoC(serviceCollection);
ConfigureLogging(serviceProvider);
var logger = LoggerFactory.CreateLogger<Program>();
logger.LogInformation("Starting Application");
ServiceRunner<IWindowsService>.Run(config =>
{
var applicationName = typeof(Program).Namespace;
config.SetName($"{applicationName}");
config.SetDisplayName($"{applicationName}");
config.SetDescription($"Service that matches Previous Buyers to Vehicles In …Run Code Online (Sandbox Code Playgroud) c# structuremap windows-services dependency-injection .net-core