Bir json dizesini alan ve ondan bir linq ifadesi oluşturan "CreateCriteriaExpression" adlı bir işleve sahibim.Bir linq ifadesiyle Covariance/Contravariance
Bu yöntem, "CreateCriteriaExpression" yöntemini çağıran ve sonra bu ifadeyi bir varlık çerçeve içeriğine karşı yürüten "GetByCriteria" adlı başka bir adla çağrılır.
Tüm varlık çerçeve nesneleri için "GetByCriteria" yöntemi, türleri dışında aynıdır. Bu yüzden, sabit kodlanmış türler yerine jenerik kullanmak için dönüştürmeye çalışıyorum.
"GetByCriteria" yöntemi, "CreateCriteriaExpression" yöntemini çağırması gereken noktaya geldiğinde, kullanmak için uygun sınıf/yöntemi belirlemek için bir fabrika sınıfı kullanıyorum. Sonra "linq ifadesi" sınıfında, belirli bir tür için linq ifadesi oluşturulur ve döndürülür.
Sahip olduğum sorun, linq ifadesinin belirli bir tür için oluşturulmasının gerekmesidir, ancak döndürülen değer, genel türdür ve otomatik olarak ikisi arasında dönüştürülmez; diğer (kovaryans).
Bu çalışmayı yapabileceğim herhangi bir yol var mı?
Bazı örnek kodu:"GetByCriteria" yöntemi:
/// <summary>
/// Gets a <see cref="System.Collections.Generic.List"/> of <see cref="TEntity"/>
/// objects that match the passed JSON string.
/// </summary>
/// <param name="myCriteria">A list of JSON strings containing a key/value pair of "parameterNames" and "parameterValues".</param>
/// <param name="myMatchMethod">Defines which matching method to use when finding matches on the <paramref name="myCriteria"/>.</param>
/// <returns>
/// A <see cref="System.Collections.Generic.List"/> of <see cref="TEntity"/>
/// objects.
/// </returns>
/// <seealso cref="TEntity"/>
///
/// <seealso cref="Common.MultipleCriteriaMatchMethod"/>
/// <remarks>
/// This method takes a <see cref="System.Collections.Generic.List"/> of JSON strings, and a <see cref="Common.MultipleCriteriaMatchMethod"/> and returns a
/// <see cref="System.Collections.Generic.List"/> of all matching
/// <see cref="TEntity"/> objects from the back-end database. The <paramref name="myMatchMethod"/> is used to determine how to match when multiple <paramref name="myCriteria"/> are passed. You can require that any results must match on ALL the passed JSON criteria, or on ANY of the passed criteria. This is essentially an "AND" versus and "OR" comparison.
/// </remarks>
[ContractVerification(true)]
public static List<TEntity> GetByCriteria<TContext, TEntity>(List<string> myCriteria, Common.MultipleCriteriaMatchMethod myMatchMethod)
where TContext : System.Data.Objects.ObjectContext, new()
where TEntity : System.Data.Objects.DataClasses.EntityObject
{
// Setup Contracts
Contract.Requires(myCriteria != null);
TContext db = new TContext();
// Intialize return variable
List<TEntity> result = null;
// Initialize working variables
// Set the predicates to True by default (for "AND" matches)
var predicate = PredicateBuilder.True<TEntity>();
var customPropertiesPredicate = PredicateBuilder.True<TEntity>();
// Set the predicates to Falase by default (for "OR" matches)
if (myMatchMethod == Common.MultipleCriteriaMatchMethod.MatchOnAny)
{
predicate = PredicateBuilder.False<TEntity>();
customPropertiesPredicate = PredicateBuilder.False<TEntity>();
}
// Loop over each Criteria object in the passed list of criteria
foreach (string x in myCriteria)
{
// Set the Criteria to local scope (sometimes there are scope problems with LINQ)
string item = x;
if (item != null)
{
JsonLinqParser parser = JsonLinqParserFactory.GetParser(typeof(TEntity));
// If the designated MultipleCriteriaMatchMethod is "MatchOnAll" then use "AND" statements
if (myMatchMethod == Common.MultipleCriteriaMatchMethod.MatchOnAll)
{
predicate = predicate.Expand().And<TEntity>(parser.CreateCriteriaExpression<TEntity>(item).Expand());
customPropertiesPredicate = customPropertiesPredicate.Expand().And<TEntity>(parser.CreateCriteriaExpressionForCustomProperties<TEntity>(item).Expand());
}
// If the designated MultipleCriteriaMatchMethod is "MatchOnAny" then use "OR" statements
else if (myMatchMethod == Common.MultipleCriteriaMatchMethod.MatchOnAny)
{
predicate = predicate.Expand().Or<TEntity>(parser.CreateCriteriaExpression<TEntity>(item).Expand());
customPropertiesPredicate = customPropertiesPredicate.Expand().Or<TEntity>(parser.CreateCriteriaExpressionForCustomProperties<TEntity>(item).Expand());
}
}
}
// Set a temporary var to hold the results
List<TEntity> qry = null;
// Set some Contract Assumptions to waive Static Contract warnings on build
Contract.Assume(predicate != null);
Contract.Assume(customPropertiesPredicate != null);
// Run the query against the backend database
qry = db.CreateObjectSet<TEntity>().AsExpandable<TEntity>().Where<TEntity>(predicate).ToList<TEntity>();
//qry = db.CreateObjectSet<TEntity>().Where(predicate).ToList<TEntity>();
// Run the query for custom properties against the resultset obtained from the database
qry = qry.Where<TEntity>(customPropertiesPredicate.Compile()).ToList<TEntity>();
// Verify that there are results
if (qry != null && qry.Count != 0)
{
result = qry;
}
// Return the results
return result;
}
JsonLinqParser sınıfı (yapı değildir):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using LinqKit;
using Newtonsoft.Json.Linq;
namespace DAL
{
internal class JsonLinqParser_Paser : JsonLinqParser
{
internal override System.Linq.Expressions.Expression<Func<TEntity, bool>> CreateCriteriaExpression<TEntity>(string myCriteria)
{
var predicate = PredicateBuilder.True<BestAvailableFIP>();
JObject o = JObject.Parse(myCriteria);
// bmp
decimal _bmp;
if (o["bmp"] != null && decimal.TryParse((string)o["bmp"], out _bmp))
{
predicate = predicate.And<BestAvailableFIP>(x => x.bmp == _bmp);
}
// COUNTY
if (!string.IsNullOrWhiteSpace((string)o["COUNTY"]))
{
string _myStringValue = (string)o["COUNTY"];
predicate = predicate.And<BestAvailableFIP>(x => x.COUNTY.Contains(_myStringValue));
}
// emp
decimal _emp;
if (o["emp"] != null && decimal.TryParse((string)o["emp"], out _emp))
{
predicate = predicate.And<BestAvailableFIP>(x => x.emp == _emp);
}
// FIPSCO_STR
if (!string.IsNullOrWhiteSpace((string)o["FIPSCO_STR"]))
{
string _myStringValue = (string)o["FIPSCO_STR"];
predicate = predicate.And<BestAvailableFIP>(x => x.FIPSCO_STR.Contains(_myStringValue));
}
// FIPSCODE
double _FIPSCODE;
if (o["FIPSCODE"] != null && double.TryParse((string)o["FIPSCODE"], out _FIPSCODE))
{
predicate = predicate.And<BestAvailableFIP>(x => x.FIPSCODE == _FIPSCODE);
}
// FROMDESC
if (!string.IsNullOrWhiteSpace((string)o["FROMDESC"]))
{
string _myStringValue = (string)o["FROMDESC"];
predicate = predicate.And<BestAvailableFIP>(x => x.FROMDESC.Contains(_myStringValue));
}
// LANEMI
decimal _LANEMI;
if (o["LANEMI"] != null && decimal.TryParse((string)o["LANEMI"], out _LANEMI))
{
predicate = predicate.And<BestAvailableFIP>(x => x.LANEMI == _LANEMI);
}
// MPO_ABBV
if (!string.IsNullOrWhiteSpace((string)o["MPO_ABBV"]))
{
string _myStringValue = (string)o["MPO_ABBV"];
predicate = predicate.And<BestAvailableFIP>(x => x.MPO_ABBV.Contains(_myStringValue));
}
// owner
if (!string.IsNullOrWhiteSpace((string)o["owner"]))
{
string _myStringValue = (string)o["owner"];
predicate = predicate.And<BestAvailableFIP>(x => x.owner.Contains(_myStringValue));
}
// PASER
decimal _PASER;
if (o["PASER"] != null && decimal.TryParse((string)o["PASER"], out _PASER))
{
predicate = predicate.And<BestAvailableFIP>(x => x.PASER == _PASER);
}
// PASER_GROUP
if (!string.IsNullOrWhiteSpace((string)o["PASER_GROUP"]))
{
string _myStringValue = (string)o["PASER_GROUP"];
predicate = predicate.And<BestAvailableFIP>(x => x.PASER_GROUP.Contains(_myStringValue));
}
// pr
decimal _pr;
if (o["pr"] != null && decimal.TryParse((string)o["pr"], out _pr))
{
predicate = predicate.And<BestAvailableFIP>(x => x.pr == _pr);
}
// RDNAME
if (!string.IsNullOrWhiteSpace((string)o["RDNAME"]))
{
string _myStringValue = (string)o["RDNAME"];
predicate = predicate.And<BestAvailableFIP>(x => x.RDNAME.Contains(_myStringValue));
}
// SPDR_ABBV
if (!string.IsNullOrWhiteSpace((string)o["SPDR_ABBV"]))
{
string _myStringValue = (string)o["SPDR_ABBV"];
predicate = predicate.And<BestAvailableFIP>(x => x.SPDR_ABBV.Contains(_myStringValue));
}
// TODESC
if (!string.IsNullOrWhiteSpace((string)o["TODESC"]))
{
string _myStringValue = (string)o["TODESC"];
predicate = predicate.And<BestAvailableFIP>(x => x.TODESC.Contains(_myStringValue));
}
// TYPE
if (!string.IsNullOrWhiteSpace((string)o["TYPE"]))
{
string _myStringValue = (string)o["TYPE"];
predicate = predicate.And<BestAvailableFIP>(x => x.TYPE.Contains(_myStringValue));
}
return predicate;
}
internal override System.Linq.Expressions.Expression<Func<TEntity, bool>> CreateCriteriaExpressionForCustomProperties<TEntity>(string myCriteria)
{
var predicate = PredicateBuilder.True<TEntity>();
return predicate;
}
}
}
JsonLinqParser temel sınıf:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;
namespace DAL
{
abstract class JsonLinqParser
{
abstract internal Expression<Func<TEntity, bool>> CreateCriteriaExpression<TEntity>(string myCriteria)
where TEntity : System.Data.Objects.DataClasses.EntityObject;
abstract internal Expression<Func<TEntity, bool>> CreateCriteriaExpressionForCustomProperties<TEntity>(string myCriteria)
where TEntity : System.Data.Objects.DataClasses.EntityObject;
}
}
fabrika sınıfı:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace DAL
{
internal static class JsonLinqParserFactory
{
internal static JsonLinqParser GetParser(Type type)
{
switch (type.Name)
{
case "BestAvailableFIP":
return new JsonLinqParser_Paser();
default:
//if we reach this point then we failed to find a matching type. Throw
//an exception.
throw new Exception("Failed to find a matching JsonLinqParser in JsonLinqParserFactory.GetParser() - Unknown Type: " + type.Name);
}
}
}
}
Teşekkürler. Bunu çalışmak için var! IoC'ye bakacağım. Bunu daha önce okumuştum, ama kafamın etrafına dolanmak benim için zamanım olduğundan biraz daha fazlaydı. Tekrar gözden geçirilmeye değer. –