![](/img/trans.png)
[英]How can I get around my “object reference” issue when passing messages to an actor?
[英]How can I get around this issue with interfaces?
我正在使用實體框架,這就是我的問題所在,但它可能不相關,因為我認為這是一個通用的C#問題。
我有一個MyContext
類,它有許多DbSet<T>
屬性。
為了對它進行單元測試,我編輯了MyContext,所以這些是IDbSet<T>
而是模擬它。 IDbSet<T>
是Entity Framework的一部分,DbSet實現它,因此兩者幾乎完全相同。
一切都很像這樣,因為我可以做IDbSet<T>
我可以對DbSet<T>
做的一切
除了一件事之外的一切DbSet
有一個叫做SqlQuery(..)
的方法,我也希望能夠從我的IDbSet
調用IDbSet
。
由於我不能改變DbSet
或IDbSet
,這給我留下了一個難題。 我無法理解我是如何做到這一點所以我的IDbSet
能夠以某種邏輯方式添加一個SearchQuery(..)
方法。
那有意義嗎? 我很困惑所以我可能忽略了一些非常簡單的東西,比如復制和粘貼IDbSet
並重命名它並添加SearchQuery()
。 有任何想法嗎?
編輯
我相信我得到了你想要的東西 - 到處都是包裝紙,可能比它的價值更麻煩,但值得一看:
// An interface which implements IDbSet<T> and adds on the method you want
public interface IExtendedDbSet<T> : IDbSet<T>
where T : class
{
DbSqlQuery<T> SqlQuery(string sql, object[] parameters);
}
// Implement this interface by wrapping around a regular DbSet<T>.
// You implement all the methods and properties by just wrapping the DbSet<T>
// calls
public class ExtendedDbSet<T> : IExtendedDbSet<T>
where T : class
{
private readonly DbSet<T> _dbSet;
public ExtendedDbSet(DbSet<T> dbSet) { _dbSet = dbSet; }
DbSqlQuery<T> IExtendedDbSet<T>.SqlQuery(string sql, object[] parameters)
{
return _dbSet.SqlQuery(sql, parameters);
}
T IDbSet<T>.Add(T entity) { return _dbSet.Add(entity); }
T IDbSet<T>.Attach(T entity) { return _dbSet.Attach(entity); }
TDerivedEntity IDbSet<T>.Create<TDerivedEntity>() { return _dbSet.Create<TDerivedEntity>(); }
T IDbSet<T>.Create() { return _dbSet.Create(); }
T IDbSet<T>.Find(params object[] keyValues) { return _dbSet.Find(keyValues); }
ObservableCollection<T> IDbSet<T>.Local { get { return _dbSet.Local; } }
T IDbSet<T>.Remove(T entity) { return _dbSet.Remove(entity); }
IEnumerator<T> IEnumerable<T>.GetEnumerator() { return ((IEnumerable<T>)_dbSet).GetEnumerator(); }
IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)_dbSet).GetEnumerator(); }
Type IQueryable.ElementType { get { return ((IQueryable)_dbSet).ElementType; } }
Expression IQueryable.Expression { get { return ((IQueryable)_dbSet).Expression; } }
IQueryProvider IQueryable.Provider { get { return ((IQueryable)_dbSet).Provider; } }
}
// A regular context class, no special interfaces to implement or
// custom properties or anything.
public class MyContext : DbContext
{
public DbSet<Car> Cars { get; set; }
}
// An interface representing your context, which exposes extended DbSet<T>
// for your sets. Also define SaveChanges() and whatever else you may need
// to call on your context object.
public interface IMyContext
: IDisposable
{
IExtendedDbSet<Car> Cars { get; }
int SaveChanges();
}
// A wrapper around your regular context. For each set, return an
// ExtendedDbSet<T> wrapper.
public class MyContextWrapper : IMyContext
{
private readonly MyContext _myContext;
public MyContextWrapper(MyContext myContext) { _myContext = myContext; }
IExtendedDbSet<Car> IMyContext.Cars
{
get { return new ExtendedDbSet<Car>(_myContext.Cars); }
}
void IDisposable.Dispose()
{
_myContext.Dispose();
}
int IMyContext.SaveChanges()
{
return _myContext.SaveChanges();
}
}
// Define your context variable as IMyContext, and create it
// by creating a wrapper around a regular context. The properties
// of the interface will be extended wrappers around your sets.
internal class Program
{
private static void Main(string[] args)
{
using (IMyContext context = new MyContextWrapper(new MyContext()))
{
Console.WriteLine(context.Cars.SqlQuery("select 1", new object[0]));
}
}
}
嗯,它可能不是最優雅的解決方案,但您可以簡單地編寫這樣的擴展方法:
public IEnumerable<T> SearchQuery(this IDbSet<T> set, string query)
{
var dbSet = set as DbSet<T>;
if (dbSet != null)
{
return dbSet.SqlQuery(query);
}
else
{
throw new NotSupportedException();
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.