2011-01-12 18 views
1

例如,給定一個廠用的方法使用存儲庫時,類型是否可以返回存儲庫用於測試現有實體的Func?

public static T Save<T>(T item) where T : Base, new() 
{ 
    /* item.Id == Guid.Empty therefore item is new */ 
    if (item.Id == Guid.Empty && repository.GetAll<T>(t => t.Name == item.Name)) 
    { 
    throw new Exception("Name is not unique"); 
    } 
} 

如何創建的Base屬性(比如MustNotAlreadyExist),這樣我可以改變上面

public static T Save<T>(T item) where T : Base, new() 
{ 
    /* item.Id == Guid.Empty therefore item is new */ 
    if (item.Id == Guid.Empty && repository.GetAll<T>(t.MustNotAlreadyExist)) 
    { 
    throw new Exception("Name is not unique"); 
    } 
} 

public class Base 
{ 
    ... 
    public virtual Expression<Func<T, bool>> MustNotAlreadyExist() 
    { 
    return (b => b.Name == name); /* <- this clearly doesn't work */ 
    } 
} 

,然後方法怎麼可以在Account : Base

public class Account : Base 
{ 
    ... 
    public override Expression<Func<T, bool>> MustNotAlreadyExist() 
    { 
    return (b => b.Name == name && b.AccountCode == accountCode); /* <- this doesn't work */ 
    } 
    ... 
} 
+0

我認爲我可能有方法簽名,雖然我很苦惱它:public virtual Expression > MustNotAlreadyExists (T item)where T:Base {return(t => t。 Name == item.Name); } – 2011-01-12 15:49:39

+0

請參閱下面我自己的答案;使用通用接口並在類型 – 2011-01-13 14:52:19

回答

0

OK東西,你可以外包呼叫GETALL,這裏就是答案,這是張貼戴夫Swersky碼的組合還有一點點常識。

public interface IUniqueable<T> 
{ 
    Expression<Func<T, bool>> Unique { get; } 
} 

public class Base, IUniqueable<Base> 
{ 
    ... 
    public Expression<Func<Base, bool>> Unique 
    { 
    get 
    { 
     var xParam = Expression.Parameter(typeof(Base), typeof(Base).Name); 
     MemberExpression leftExprFieldCheck = MemberExpression.Property(xParam, "Name"); 
     Expression rightExprFieldCheck = Expression.Constant(this.Name); 
     BinaryExpression binaryExprFieldCheck = MemberExpression.Equal(leftExprFieldCheck, rightExprFieldCheck); 
     return Expression.Lambda<Func<Base, bool>>(binaryExprFieldCheck, new ParameterExpression[] { xParam }); 
    } 
    } 
    ... 
} 

public class Account : Base, IUniqueable<Account> 
{ 
    ... 
    public new Expression<Func<Account, bool>> Unique 
    { 
    get 
    { 
     var xParam = Expression.Parameter(typeof(Account), typeof(Account).Name); 
     MemberExpression leftExprNameCheck = MemberExpression.Property(xParam, "Name"); 
     Expression rightExprNameCheck = Expression.Constant(this.Name); 
     BinaryExpression binaryExprNameCheck = MemberExpression.Equal(leftExprNameCheck, rightExprNameCheck); 

     MemberExpression leftExprFieldCheck = MemberExpression.Property(xParam, "AccountCode"); 
     Expression rightExprFieldCheck = Expression.Constant(this.AccountCode); 
     BinaryExpression binaryExprFieldCheck = MemberExpression.Equal(leftExprFieldCheck, rightExprFieldCheck); 

     BinaryExpression binaryExprAllCheck = Expression.OrElse(binaryExprNameCheck, binaryExprFieldCheck); 

     return Expression.Lambda<Func<Account, bool>>(binaryExprAllCheck, new ParameterExpression[] { xParam }); 
    } 
    } 
    ... 
} 

public static class Manager 
{ 
    ... 
    public static T Save<T>(T item) where T : Base, new() 
    { 
    if (!item.IsValid) 
    { 
     throw new ValidationException("Unable to save item, item is not valid", item.GetRuleViolations()); 
    } 

    if (item.Id == Guid.Empty && repository.GetAll<T>().Any(((IUniqueable<T>)item).Unique)) 
    { 
     throw new Exception("Item is not unique"); 
    } 

    return repository.Save<T>(item); 
    } 
    ... 
} 

基本上通過實施IUniqueable接口對於特定類型的我可以爲每種類型返回不同Expression。所有好的:-)

2

覆蓋MustNotAlreadyExist試試這個:

public class Account : Base 
{ 
    ... 
    public override Expression<Func<T, bool>> MustNotAlreadyExist() 
    { 
    return (b => b.Name == name && b.AccountCode == accountCode).Any(); 
    } 
    ... 
} 

如果任何記錄與謂詞匹配,Any()方法將返回true。有人可能會認爲,保存之前檢查記錄的存在是否在存儲庫的責任範圍之外。

UPDATE:
有描述一個通用存儲庫實體框架在CodeProject上一大篇:

http://www.codeproject.com/KB/database/ImplRepositoryPatternEF.aspx

這可以被應用到非實體框架數據上下文。這是一個摘錄,它提供了一個非常靈活的方法,通過接受字段名稱,值和鍵值來檢查現有值。您可以將其應用於任何實體類型,並在嘗試保存之前使用它來檢查實體的存在。

/// <summary> 
    /// Check if value of specific field is already exist 
    /// </summary> 
    /// <typeparam name="E"></typeparam> 
    /// <param name="fieldName">name of the Field</param> 
    /// <param name="fieldValue">Field value</param> 
    /// <param name="key">Primary key value</param> 
    /// <returns>True or False</returns> 
    public bool TrySameValueExist(string fieldName, object fieldValue, string key) 
    { 
     // First we define the parameter that we are going to use the clause. 
     var xParam = Expression.Parameter(typeof(E), typeof(E).Name); 
     MemberExpression leftExprFieldCheck = 
     MemberExpression.Property(xParam, fieldName); 
     Expression rightExprFieldCheck = Expression.Constant(fieldValue); 
     BinaryExpression binaryExprFieldCheck = 
     MemberExpression.Equal(leftExprFieldCheck, rightExprFieldCheck); 

     MemberExpression leftExprKeyCheck = 
     MemberExpression.Property(xParam, this._KeyProperty); 
     Expression rightExprKeyCheck = Expression.Constant(key); 
     BinaryExpression binaryExprKeyCheck = 
     MemberExpression.NotEqual(leftExprKeyCheck, rightExprKeyCheck); 
     BinaryExpression finalBinaryExpr = 
     Expression.And(binaryExprFieldCheck, binaryExprKeyCheck); 

     //Create Lambda Expression for the selection 
     Expression<Func<E, bool>> lambdaExpr = 
     Expression.Lambda<Func<E, bool>>(finalBinaryExpr, 
     new ParameterExpression[] { xParam }); 
     //Searching ....    
     return ((IRepository<E, C>)this).TryEntity(new Specification<E>(lambdaExpr)); 
    } 
    /// <summary> 
    /// Check if Entities exist with Condition 
    /// </summary> 
    /// <param name="selectExpression">Selection Condition</param> 
    /// <returns>True or False</returns> 
    public bool TryEntity(ISpecification<E> selectSpec) 
    { 
     return _ctx.CreateQuery<E>("[" + typeof(E).Name + "]").Any<E> 
        (selectSpec.EvalPredicate); 
    } 
+0

中實現此特定類型這不會編譯...我想從此方法返回的是我可以傳入GetAll()的Expression(或Func)。任何...)電話。 – 2011-01-12 15:31:57

1

我不是舒爾如果你的問題是可以解決的,因爲你需要同時訪問存儲庫和新項目進行檢查。要檢查的新項目不能用單獨的方法提供。

但是讓你的代碼變得類似於 (未測試)

public static T Save<T>(T item) where T : Base, new() 
{ 
    if (item.Id == Guid.Empty && (Check(repository, item))) 
    { 
    throw new Exception("Name is not unique"); 
    } 
} 

public class Base 
{ 
    ... 
    public Func<Enumerable<T>, T, bool> Check { get; set;} 

    public Base() 
    { 
    Check = (col, newItem) => (null != col.FirstOrDefault<T>(
             item => item.Name == newItem.Name)); 
    } 
}