如何解决 Autofac 中需要路由参数的 WebAPI 依赖项?
How do I resolve a WebAPI dependency in Autofac that requires a parameter from the route?
我正在努力通过我的 WebApi 2 项目中的 autofac 连接依赖项。我有一个以下接口和 class 我想在我的 GET 和 POST 控制器操作中注入,
public interface IRepository
{
IContext Context
{
get;
}
void SomeOperation();
}
public MyRepository : IRepository
{
IContext _context;
public MyRepository(IContext context)
{
_context = context;
}
public Context
{
get
{
return _context;
}
}
public void SomeOperation
{
// Perform some operation using _context;
}
}
我希望像这样将 IRepository 注入到控制器中,
public class MyController : ApiController
{
private readonly IRepository _repo;
public ApplicationsController(IRepository repo)
{
_repo = repo;
}
// GET: api/v1/Contexts({contextId})
public IHttpActionResult Get(string contextId)
{
_repo.SomeOperation();
}
}
要注入到 MyRepository 中的 IContext 对象必须从工厂中获取,像这样
public class ContextFactory
{
Hashtable contextMap;
IContext Get(string contextId)
{
if contextMap.Contains(contextId)
return contextMap[contextId].Value;
else
{
IContextConfiguration configuration = ContextConfigurationFactory.Get(contextId);
IContext context = new ConcreteContext(configuration);
contextMap.Add[contextId, context];
return context;
}
}
}
我不确定如何通过 Autofac 注入关系来连接所有 classes 并转换工厂 classes 中的逻辑,以便将 url 中传递的上下文 ID 传递给ContextConfigurationFactory.Get 并在哈希中找不到时实例化 ConcreteContext 对象,最终 Autofac 在 MyRepository 中注入正确的上下文对象,然后再将其传递给控制器中的 Get 操作。
让我们稍微简化一下。您要做的是:
- 从路由参数中获取上下文 ID。
- 在工厂中使用该路由参数创建上下文。
其余的看起来几乎是外围的 - 存储库、控制器,所有这些。问题的症结在于你需要获取一个路由参数进入你的工厂。
鉴于此,让我们整理一些简化的代码:
public class ContextFactory
{
public IContext Get(string contextId)
{
return new Context(contextId);
}
}
public interface IContext
{
string Id { get; }
}
public class Context : IContext
{
public Context(string id)
{
this.Id = id;
}
public string Id { get; private set; }
}
这基本上就是你所拥有的:
- 事物需要的
IContext
接口。
- 一个
ContextFactory
,基本上负责构建这些东西。
- 工厂构建的
IContext
的Context
具体实现。
我可能会这样做:
var builder = new ContainerBuilder();
builder.RegisterType<ContextFactory>();
builder.Register(ctx =>
{
var routeData = HttpContext.Current.Request.RequestContext.RouteData;
var id = routeData.Values["contextId"] as string;
var factory = ctx.Resolve<ContextFactory>();
return factory.Get(id);
}).As<IContext>()
.InstancePerLifetimeScope();
现在,当您解析 IContext
时,它将使用您的工厂,从路由数据中获取当前上下文 ID,并将其传递给工厂。
我将留下以下内容供您查看:
- 如果路由参数不存在会怎样? (Autofac 不会让你 return 为空。)
- 如果路由参数有无效数据会怎样?
- 路由参数很容易破解,这是安全风险吗?
...等等。
我正在努力通过我的 WebApi 2 项目中的 autofac 连接依赖项。我有一个以下接口和 class 我想在我的 GET 和 POST 控制器操作中注入,
public interface IRepository
{
IContext Context
{
get;
}
void SomeOperation();
}
public MyRepository : IRepository
{
IContext _context;
public MyRepository(IContext context)
{
_context = context;
}
public Context
{
get
{
return _context;
}
}
public void SomeOperation
{
// Perform some operation using _context;
}
}
我希望像这样将 IRepository 注入到控制器中,
public class MyController : ApiController
{
private readonly IRepository _repo;
public ApplicationsController(IRepository repo)
{
_repo = repo;
}
// GET: api/v1/Contexts({contextId})
public IHttpActionResult Get(string contextId)
{
_repo.SomeOperation();
}
}
要注入到 MyRepository 中的 IContext 对象必须从工厂中获取,像这样
public class ContextFactory
{
Hashtable contextMap;
IContext Get(string contextId)
{
if contextMap.Contains(contextId)
return contextMap[contextId].Value;
else
{
IContextConfiguration configuration = ContextConfigurationFactory.Get(contextId);
IContext context = new ConcreteContext(configuration);
contextMap.Add[contextId, context];
return context;
}
}
}
我不确定如何通过 Autofac 注入关系来连接所有 classes 并转换工厂 classes 中的逻辑,以便将 url 中传递的上下文 ID 传递给ContextConfigurationFactory.Get 并在哈希中找不到时实例化 ConcreteContext 对象,最终 Autofac 在 MyRepository 中注入正确的上下文对象,然后再将其传递给控制器中的 Get 操作。
让我们稍微简化一下。您要做的是:
- 从路由参数中获取上下文 ID。
- 在工厂中使用该路由参数创建上下文。
其余的看起来几乎是外围的 - 存储库、控制器,所有这些。问题的症结在于你需要获取一个路由参数进入你的工厂。
鉴于此,让我们整理一些简化的代码:
public class ContextFactory
{
public IContext Get(string contextId)
{
return new Context(contextId);
}
}
public interface IContext
{
string Id { get; }
}
public class Context : IContext
{
public Context(string id)
{
this.Id = id;
}
public string Id { get; private set; }
}
这基本上就是你所拥有的:
- 事物需要的
IContext
接口。 - 一个
ContextFactory
,基本上负责构建这些东西。 - 工厂构建的
IContext
的Context
具体实现。
我可能会这样做:
var builder = new ContainerBuilder();
builder.RegisterType<ContextFactory>();
builder.Register(ctx =>
{
var routeData = HttpContext.Current.Request.RequestContext.RouteData;
var id = routeData.Values["contextId"] as string;
var factory = ctx.Resolve<ContextFactory>();
return factory.Get(id);
}).As<IContext>()
.InstancePerLifetimeScope();
现在,当您解析 IContext
时,它将使用您的工厂,从路由数据中获取当前上下文 ID,并将其传递给工厂。
我将留下以下内容供您查看:
- 如果路由参数不存在会怎样? (Autofac 不会让你 return 为空。)
- 如果路由参数有无效数据会怎样?
- 路由参数很容易破解,这是安全风险吗?
...等等。