C# 使用Try-Catch块包装复杂的linq查询并捕获正确的异常
下面的代码是一个工厂类,它提供了实现了GraphTypeAttribute的IGraph类型的对象。在GraphFactory的静态构造函数中,通过使用Linq收集工厂要交付的适当类来构建一个列表。通常没有Linq的情况下,我会有一堆循环,如果有,那么可以用合适的try-catch块轻松包装由于所有内容都塞进了一个查询中,现在我对如何在这里实现适当的异常处理有点困惑 所以我的问题是/是C# 使用Try-Catch块包装复杂的linq查询并捕获正确的异常,c#,linq,exception-handling,singleton,factory,C#,Linq,Exception Handling,Singleton,Factory,下面的代码是一个工厂类,它提供了实现了GraphTypeAttribute的IGraph类型的对象。在GraphFactory的静态构造函数中,通过使用Linq收集工厂要交付的适当类来构建一个列表。通常没有Linq的情况下,我会有一堆循环,如果有,那么可以用合适的try-catch块轻松包装由于所有内容都塞进了一个查询中,现在我对如何在这里实现适当的异常处理有点困惑 所以我的问题是/是 处理linq查询异常的最佳模式是什么 我应该把它分成不同的查询还是根本不使用linq 或者我在查询中误解了一
- 处理linq查询异常的最佳模式是什么
- 我应该把它分成不同的查询还是根本不使用linq李>
- 或者我在查询中误解了一些可以消除不存在的元素、扫描错误的类等、查询重复的值等(优化查询;)
public sealed class GraphFactory
{
static readonly GraphFactory _instance = new GraphFactory();
static readonly IDictionary<string, Type> _items;
static readonly Assembly _assembly = Assembly.GetExecutingAssembly();
public static GraphFactory Instance { get { return _instance; } }
GraphFactory() { }
static GraphFactory() {
try
{
_items = (from type in _assembly.GetTypes()
// filter from thatonly the classes with IGraph implemented
where type.GetInterface(typeof(IGraph).FullName) != null
// filter from thatonly the classes with GraphTypeAttribute imp.
from attribute in type.GetCustomAttributes(true)
where attribute is GraphTypeAttribute
select new { attribute, type })
// convert the result from anonymous to a dictionary
.ToDictionary(k => (k.attribute as GraphTypeAttribute).CustomType,
e => e.type);
}
/** EXH: non pokemon exception handling * ........... * **/
}
public static IEnumerable<string> FriendlyNames { get { return _items.Keys; } }
public static IGraph CreateGraph(string friendlyName)
{
/** inspect argument, check it's a key
in the dictionary and throw exeptions if needed **/
IGraph result = null;
try
{
result = _assembly.CreateInstance(_items[friendlyName].FullName) as IGraph;
}
/** non pokemon exception handling * ........... * **/
return result;
}
}
属性来装饰工厂分配的适当类
[AttributeUsage(AttributeTargets.Class, AllowMultiple=false,Inherited=true)]
public class GraphTypeAttribute : System.Attribute
{ public GraphTypeAttribute(string friendlyName) { } }
用属性修饰的类
[GraphTypeAttribute("piechart")]
public class PieChart : IGraph{ }
[GraphTypeAttribute("map")]
public class WorldMap : IGraph { }
[GraphTypeAttribute("horizontalbar")]
public class Bar : IGraph { }
[GraphTypeAttribute("verticalbar")]
public class VerticalBar : Bar { }
示例用法:
foreach (string friendlyName in GraphFactory.FriendlyNames)
{
IGraph auth = GraphFactory.CreateGraph(friendlyName);
}
感谢您对本课程的任何其他评论或建议。我认为这是一个很好的例子。我总是这样做。我理解您对异常处理的担忧,但我认为没有必要这样做,因为您的单元测试将防止工厂在生产过程中抛出异常,而良好的单元测试可以像异常消息一样清楚地解释问题 但是,如果您真的想进行错误检查,您的LINQ查询将永远不会抛出异常。当有双键时,将抛出的是
ToDictionary
。您可以做的是验证LINQ查询的结果并传递双键:
static GraphFactory()
{
var items = (
from type in _assembly.GetTypes()
where type.GetInterface(typeof(IGraph).FullName) != null
from attribute in type.GetCustomAttributes(true)
.OfType<GraphTypeAttribute>
select new { attribute, type }).ToArray();
ValidateTypes(items);
_item = items.ToDictionary(
k => k.attribute.CustomType, e => e.type);
}
private static void ValidateTypes<T>(T[] items)
{
var firstDoubleCustomType = (
from item in items
group item by item.attribute.CustomType into g
where g.Count() > 1
select g.Key).FirstOrDefault();
if (firstDoubleCustomType != null)
{
throw new InvalidProgramException(
"Doube: " + firstDoubleCustomType.ToString());
}
}
staticgraphfactory()
{
可变项目=(
从_assembly.GetTypes()中键入
其中type.GetInterface(typeof(IGraph.FullName)!=null
来自type.GetCustomAttributes中的属性(true)
.字体
选择新的{attribute,type}).ToArray();
验证类型(项目);
_item=items.ToDictionary(
k=>k.attribute.CustomType,e=>e.type);
}
私有静态void validateType(T[]项)
{
var firstDoubleCustomType=(
从项目中的项目
按item.attribute.CustomType将项目分组到g中
其中g.Count()>1
选择g.Key).FirstOrDefault();
if(firstDoubleCustomType!=null)
{
抛出新的InvalidProgrammeException(
“Doube:+firstDoubleCustomType.ToString());
}
}
很抱歉,我不能将函数放在构造函数之外,异常不会以这种方式暴露在类之外;)。字体看起来还是不错的;)谢谢和链接到文件是伟大的@卡斯珀:我只是想让我的例子可读。如果愿意,您可以将其全部内联放置。@Casper:您也可以在静态构造函数中创建一次所有实例(为什么不简单地使用Activator.CreateInstance(Type)
)。当存在无效类型时,这将使系统快速故障。当这是一个问题时,将您的使用示例放在单元测试中似乎是一个好主意。有足够的单元测试可以避免很多糟糕的错误处理,只需对代码稍加修改就可以了。谢谢
static GraphFactory()
{
var items = (
from type in _assembly.GetTypes()
where type.GetInterface(typeof(IGraph).FullName) != null
from attribute in type.GetCustomAttributes(true)
.OfType<GraphTypeAttribute>
select new { attribute, type }).ToArray();
ValidateTypes(items);
_item = items.ToDictionary(
k => k.attribute.CustomType, e => e.type);
}
private static void ValidateTypes<T>(T[] items)
{
var firstDoubleCustomType = (
from item in items
group item by item.attribute.CustomType into g
where g.Count() > 1
select g.Key).FirstOrDefault();
if (firstDoubleCustomType != null)
{
throw new InvalidProgramException(
"Doube: " + firstDoubleCustomType.ToString());
}
}