我想通过在字符串变量 refName 中拥有的名称来反映MVC项目的模型类。当前我正在使用switch case将那些类用作模板,即
基本上,我要做的是根据 gRefType 字段将cosmos db中的数据收集为特定的模板类格式。这是我所做的:
IEnumerable<Object> itemsRefDetail;
switch (refName)
{
case "AMCaseStatus":
itemsRefDetail = await DocumentDBRepository<AMCaseStatus>.GetItemRefDetailAsync(p => p.GrefType == refName && p.Tag == tag, collectionId);
break;
case "AMcaseSubStatus":
itemsRefDetail = await DocumentDBRepository<AMcaseSubStatus>.GetItemRefDetailAsync(p => p.GrefType == refName && p.Tag == tag, collectionId);
break;
case "AMRole":
itemsRefDetail = await DocumentDBRepository<AMRole>.GetItemRefDetailAsync(p => p.GrefType == refName && p.Tag == tag, collectionId);
break;
}
如上面的代码所示,每种情况下使用的Template类与case值相同。所有类都具有相同的属性(GrefType和Tag)。
这是DocumentDbRepository类:
public static class DocumentDBRepository<T> where T : class
{
public static async Task<IEnumerable<T>> GetItemRefDetailAsync(Expression<Func<T, bool>> predicate, string collectionId)
{
IDocumentQuery<T> query = client.CreateDocumentQuery<T>(
UriFactory.CreateDocumentCollectionUri(DatabaseId, collectionId))
.Where(predicate)
.AsDocumentQuery();
FeedResponse<T> privilegeQueryResponse = await query.ExecuteNextAsync<T>();
return privilegeQueryResponse;
}
}
答案 0 :(得分:1)
我举了一个如何反映泛型类型的示例,您唯一要做的就是将GrefType
和Tag
包装到基类/接口中。这可能会给您启动的机会:
代码如下:
// The basetype of an item (which contains de RefName etc)
public class BaseType
{
public string RefName { get; set; }
public string Tag { get; set; }
}
// static T service with some testdata (mock)
public static class Data<T> where T : BaseType
{
public static List<T> MyData { get; } = new List<T>();
static Data()
{
// create an item
var item = Activator.CreateInstance<T>();
item.RefName = "Test";
item.Tag = "Bla";
MyData.Add(item);
var item2 = Activator.CreateInstance<T>();
item2.RefName = "SomethingElse";
item2.Tag = "TagThing";
MyData.Add(item2);
var item3 = Activator.CreateInstance<T>();
item3.RefName = "Test2";
item3.Tag = "Bla2";
MyData.Add(item3);
}
}
// the generic class which uses the basetype as generic
public static class DocumentDBRepository<T> where T : BaseType
{
public static IEnumerable<T> SelectData(Func<T, bool> predicate)
{
// some static test data
return Data<T>.MyData.Where(predicate);
}
}
// your derived class from BaseType
public class MyLookupThing : BaseType
{
}
class TestReflection
{
public TestReflection()
{
// you can create more classes derived from BaseType
var typeStr = "TestRef.MyLookupThing";
// resolve the type:
var lookupType = (from ass in AppDomain.CurrentDomain.GetAssemblies()
from t in ass.GetTypes()
where t.FullName == typeStr
select t).First();
// get the type of the generic class
var myType = typeof(DocumentDBRepository<>);
// create a generic type
var myGenericType = myType.MakeGenericType(lookupType);
var method = myGenericType.GetMethod("SelectData", BindingFlags.Static | BindingFlags.Public);
// Create the function (with the BaseType)
var func = new Func<BaseType, bool>(item => item.RefName.StartsWith("Test"));
// invoke the method of the generic class
IEnumerable<BaseType> result = (IEnumerable<BaseType>)method.Invoke(null, new object[] { func });
// show the results
foreach (var item in result)
Console.WriteLine(item.RefName);
Console.ReadKey();
}
}
哪个会给:
Test
Test2
结果
答案 1 :(得分:0)
在这里,您可以创建此表达式以将查询限制为以下类型:
internal static Expression<Func<TEntity, bool>> CreateTypeSpesificExpression<TEntity>(string refName) where TEntity : class
{
var parameter = Expression.Parameter(typeof(IAmObject));
var member = Expression.Property(parameter, nameof(IAmObject.GrefType));
var contant = Expression.Constant(refName);
var body = Expression.Equal(member, contant);
var extra = Expression.Lambda<Func<TEntity, bool>>(body, parameter);
return extra;
}
所有这些都假设您的AM类具有相同的接口。 完成后,您可以简单地将其添加到where子句中。
您的查询应如下所示:
IEnumerable<Object> itemsRefDetail = await DocumentDBRepository<AMCaseStatus>.GetItemRefDetailAsync(p => CreateTypeSpesificExpression(refName) && p.Tag == tag, collectionId);
还有一点需要指出的是,Cosmonaut已经对基于类型的集合共享提供了本机支持。