我正在努力使用Unity将通用类型存储库注入我的服务类。至少,我认为这个通用存储库是造成麻烦的原因。有人能指出我做错了什么吗?请原谅我,因为我是Unity的新手。首先,这里是我收到以下错误的错误信息。
解析依赖项失败,type = "TestUnity.Services.Contracts. "ICustBillingTypeService", name = "(none)"。解析。
时发生异常异常是:InvalidOperationException -类型String不能被构造。您必须配置容器来提供这个值。
异常发生时,容器为:
解析testunity . services . implementations . custbillingtypesservice,(none)(从TestUnity.Services.Contracts映射)。ICustBillingTypeService (none))解析构造函数的参数"repo"。IRepository 1[[TestUnity.DAL.CustBillingType, TestUnity.DAL, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]] repo)
Resolving TestUnity.Repositories.Implementations.Repository
[TestUnity.DAL. custbillingtype],(none)(映射自TestUnity.Repositories.Contracts.IRepository 1[TestUnity.DAL.CustBillingType], (none))
Resolving parameter "ctx" of constructor TestUnity.Repositories.Implementations.Repository
1[[TestUnity.DAL. custbillingtype])。CustBillingType TestUnity。[0], Version=1.0.0.0, Culture=neutral, PublicKeyToken=null。IDataContext ctx)解析TestUnity.Repositories.Implementations.DataContext,(none)(从testunories . repositories . contracts .映射)。IDataContext (none))解析构造函数的参数"nameOrConnectionString"。字符串nameOrConnectionString)system . string,解决(没有)
这是我的Unity引导类,它在一个单独的类库
public static class UnityBootstrap
{
private static IUnityContainer container;
public static IUnityContainer Container
{
get
{
if (container == null)
InitializeContainer();
return container;
}
}
public static void InitializeContainer()
{
container = new UnityContainer();
container.RegisterType<ICustBillingTypeService, CustBillingTypeService>();
container.RegisterType<IDataContext, DataContext>();
container.RegisterType(typeof(IRepository<>), typeof(Repository<>));
}
}
public interface IRepository<T> where T : class, IObjectState
{
T FindOne(Expression<Func<T, bool>> predicate);
}
public class Repository<T> : IRepository<T> where T : class, IObjectState
{
private readonly IDataContext context;
private readonly IDbSet<T> dbSet;
public Repository() { }
public Repository(IDataContext ctx)
{
this.context = ctx;
var dbContext = context as DbContext;
dbSet = dbContext.Set<T>();
}
public virtual T FindOne(Expression<Func<T, bool>> predicate)
{
return dbSet.SingleOrDefault(predicate);
}
}
public interface ICustBillingTypeService
{
CustBillingType GetCustBillingTypeByPKId(int pkId);
}
public class CustBillingTypeService : ICustBillingTypeService
{
IRepository<CustBillingType> custBillingTypeRepo;
public CustBillingTypeService() { }
public CustBillingTypeService(IRepository<CustBillingType> repo)
{
custBillingTypeRepo = repo;
}
public CustBillingType GetCustBillingTypeByPKId(int pkId)
{
var cbt = custBillingTypeRepo.FindOne(x => x.PKId == pkId);
return cbt;
}
}
public interface IDataContext : IDisposable
{
int SaveChanges();
void SyncObjectState<TEntity>(TEntity entity) where TEntity : class, IObjectState;
void SyncObjectsStatePostCommit();
}
public class DataContext : DbContext, IDataContext
{
private readonly Guid _instanceId;
bool _disposed;
public DataContext(string nameOrConnectionString) : base(nameOrConnectionString)
{
_instanceId = Guid.NewGuid();
Configuration.LazyLoadingEnabled = false;
Configuration.ProxyCreationEnabled = false;
}
public Guid InstanceId { get { return _instanceId; } }
public override int SaveChanges()
{
SyncObjectsStatePreCommit();
var changes = base.SaveChanges();
SyncObjectsStatePostCommit();
return changes;
}
protected override void Dispose(bool disposing)
{
if (!_disposed)
{
if (disposing)
{
}
_disposed = true;
}
base.Dispose(disposing);
}
}
public partial class TestModel : DataContext
{
public TestModel() : base("name=TestModel") {}
public virtual DbSet<CustBillingType> CustBillingTypes { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
CustBillingTypeModelBuilder.Map(modelBuilder);
}
}
[TestClass]
public class UnityTestCases
{
private IUnityContainer uContainer;
private ICustBillingTypeService icbService;
public UnityTestCases()
{
uContainer = UnityBootstrap.Container;
icbService = uContainer.Resolve<ICustBillingTypeService>();
}
[TestMethod]
public void GetCustBillingTypeByPKId_return_ValidObj()
{
var obj = icbService.GetCustBillingTypeByPKId(pkId: 15);
Assert.IsNotNull(obj);
}
}
请注意,在我的测试用例中,我没有嘲笑任何东西。这是一种集成测试
如果要我猜的话,我会认为泛型类型注册有问题。也可能完全是别的原因。
先生。
将IDataContext
映射到DataContext
:
container.RegisterType<IDataContext, DataContext>();
DataContext
构造函数需要一个连接字符串/名称作为参数,但您没有提供。
像这样提供这个值:
container.RegisterType<IDataContext, DataContext>(
new InjectionConstructor("name=TestModel"));
或者使用TestModel
代替DataContext
。我猜这就是你想要做的。TestModel
已经有一个默认构造函数,所以你不需要提供连接字符串:
container.RegisterType<IDataContext, TestModel>();
在我看来,在组合根(在你的例子中是UnityBootstrap
类)中有可见的连接字符串是有意义的,而不是在TestModel
的默认构造函数中硬编码。连接字符串基本上是一个基本依赖项,您可能希望在将来更改它。