我有一些單詞模板(可能是數千)。每個模板都具有將從數據庫填充的合併字段。我不喜歡爲每個模板編寫單獨的代碼,然後構建應用程序並在模板更改或模板上的字段添加時進行部署!從字符串構建動態LINQ查詢 - 使用反射?
相反,我試圖在一個單獨的xml文件中定義所有合併字段,並且爲每個字段我想寫入「查詢」,這將在需要時調用。 EX:
- mergefield1將調用查詢 「Case.Parties.FirstOrDefault.NameEn」
- mergefield2將調用查詢 「Case.CaseNumber」
- mergefield3將調用查詢「Case.Documents.FirstOrDefault.DocumentContent.DocumentType 「
- 等
因此,對於一個特定的模板,我掃描其合併域,併爲每個合併域我把它單曲‘查詢定義’,並使用的EntityFramework和LINQ該請求到數據庫。防爆。它適用於這些查詢:「TimeSlots.FirstOrDefault.StartDateTime」或 「Case.CaseNumber」
這將是一個引擎,它將生成word文檔並用xml中的合併字段填充它。此外,它將適用於任何新模板或新合併字段。
現在,我已經使用反射工作了一個版本。
public string GetColumnValueByObjectByName(Expression<Func<TEntity, bool>> filter = null, string objectName = "", string dllName = "", string objectID = "", string propertyName = "")
{
string objectDllName = objectName + ", " + dllName;
Type type = Type.GetType(objectDllName);
Guid oID = new Guid(objectID);
dynamic Entity = context.Set(type).Find(oID); // get Object by Type and ObjectID
string value = ""; //the value which will be filled with data from database
IEnumerable<string> linqMethods = typeof(System.Linq.Enumerable).GetMethods(BindingFlags.Static | BindingFlags.Public).Select(s => s.Name).ToList(); //get all linq methods and save them as list of strings
if (propertyName.Contains('.'))
{
string[] properies = propertyName.Split('.');
dynamic object1 = Entity;
IEnumerable<dynamic> Child = new List<dynamic>();
for (int i = 0; i < properies.Length; i++)
{
if (i < properies.Length - 1 && linqMethods.Contains(properies[i + 1]))
{
Child = type.GetProperty(properies[i]).GetValue(object1, null);
}
else if (linqMethods.Contains(properies[i]))
{
object1 = Child.Cast<object>().FirstOrDefault(); //for now works only with FirstOrDefault - Later it will be changed to work with ToList or other linq methods
type = object1.GetType();
}
else
{
if (linqMethods.Contains(properies[i]))
{
object1 = type.GetProperty(properies[i + 1]).GetValue(object1, null);
}
else
{
object1 = type.GetProperty(properies[i]).GetValue(object1, null);
}
type = object1.GetType();
}
}
value = object1.ToString(); //.StartDateTime.ToString();
}
return value;
}
我不知道這是否是最好的方法。有沒有人有更好的建議,或者有人已經做過這樣的事情?
縮短它:想法是從一個字符串,如:「Case.Parties.FirstOrDefault.NameEn」的數據庫進行通用linq查詢。
如果我以正確的方式理解你,我會推薦你使用Expression來構建linq查詢。這些東西允許你在運行時創建linq請求。 https://msdn.microsoft.com/ru-ru/library/mt654263.aspx - 這裏是一個例子 – Egorikas
謝謝Egorikas。其實Expression有點複雜。並不確定這是否也適用於我的問題。但是,我會再看看錶達式。 – drill