我正在寻找一个模式的优化,我所使用的动态表单应用程序。
我有一个存储库类,它有一个方法:
public Entity Find(string objectId, List<string> includedProperties);
这将返回一个实体对象,其中只有在"includedProperties“中指定的字段,因为为所有目的构建整个对象在本例中是不必要的(有些实体拥有数百个属性)。
使用此存储库的示例域代码通常如下所示:
var includedProperties = new List<string> {
"FirstChildName" ,
"FirstChildDob",
"SecondChildName",
"SecondChildDob"
}
然后,我获取一个对象:
var person = repository.Find("123",includedProperties);
然后,我将属性与GetProperty(string propertyName)
方法一起使用:
var firstChildDob = person.GetProperty("FirstChildDob").AsDateTime();
...etc
这一切都工作良好,并符合应用程序的动态设计。但是,在获取对象之前,我总是需要分别声明“已使用”属性的列表,这让我感到恼火。
因此,我的问题是,通过反射或其他一些聪明之处,我是否可以通过使用“”方法在代码中稍后传递哪些参数来简化“包含属性”的构建?
使用上面的示例,我希望使用这样的助手(或类似的)构建列表:
var includedProperties = HelperObject.GetFieldsUsedInCurrentCodeFile();
这将以某种方式提取传递给"GetProperty()“方法的字符串常量,从而节省了显式声明的需要。欢迎任何建议!
发布于 2014-01-04 00:37:56
事实上,不久前我也遇到了类似的问题;当时我能想到的最好的方法就是定义一个枚举,其中包含我想要在方法中使用的属性的名称。
使用这种方法,您可以通过遍历枚举来构建包含属性的列表。
这种方法与字符串相比有几个好处:
例如:
private enum PersonMethodProperties
{
FirstChildName,
FirstChildDob,
SecondChildName,
SecondChildDob
}
private void PersonMethod()
{
var includedProperties = GetIncludePropertiesFromEnum(typeof(PersonMethodProperties));
var person = repository.Find("123", includedProperties);
var firstChildDob = person.GetProperty(PersonMethodProperties.FirstChildDob.ToString()).AsDateTime();
}
private List<string> GetIncludePropertiesFromEnum(Type propertiesEnumType)
{
var includedProperties = new List<string>();
foreach (var name in Enum.GetNames(propertiesEnumType))
{
includedProperties.Add(name);
}
return includedProperties;
}
发布于 2014-01-04 01:55:01
不幸的是,像尼特里克或NDepend这样的代码分析工具无助于您,因为在当前版本中,它们不捕获方法的参数、名称和值。
但是,您可以使用罗斯林创建工具,该工具将分析解决方案,并生成一个类,其中包含一个包含已使用属性作为预构建事件的列表。查找对className
.methodName
的所有调用并返回其常量参数(在本例中为文本)的解决方案分析代码:
static IEnumerable<string> GetMethodCallParametersValues(string solutionName,
string className,
string methodName)
{
var workspace = Workspace.LoadSolution(solutionName);
var solution = workspace.CurrentSolution;
var createCommandList = new List<ISymbol>();
var @class = solution.Projects.Select(s => s.GetCompilation()
.GetTypeByMetadataName(className))
.FirstOrDefault();
var method = @class.GetMembers(methodName)
.AsList()
.Where(s => s.Kind == CommonSymbolKind.Method)
.FirstOrDefault();
var locations = method.FindReferences(solution)
.SelectMany(r => r.Locations);
List<string> result = new List<string>();
foreach (var location in locations)
{
var model = location.Document.GetSemanticModel();
var token = location.Location
.SourceTree
.GetRoot()
.FindToken(location.Location.SourceSpan.Start);
var invocation = token.Parent.FirstAncestorOrSelf<InvocationExpressionSyntax>();
var arguments = invocation.ArgumentList.Arguments;
result.AddRange(arguments.Select(a => model.GetConstantValue(a.Expression).Value.ToString()));
}
return result.Distinct();
}
以及代码使用情况:
var includedProperties = GetMethodCallParametersValues(@"c:\path\to\your.sln",
"SomeNamespace.SomeClass",
"GetProperty");
注意事项:由于Roslyn在解析解决方案文件中的小错误,您可能不得不在.sln
文件中添加#
来注释下面的行,以便它们看起来:
# VisualStudioVersion = 12.0.21005.1
# MinimumVisualStudioVersion = 10.0.40219.1
https://stackoverflow.com/questions/20914971
复制相似问题