Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/jsf-2/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用Try-Catch块包装复杂的linq查询并捕获正确的异常_C#_Linq_Exception Handling_Singleton_Factory - Fatal编程技术网

C# 使用Try-Catch块包装复杂的linq查询并捕获正确的异常

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 或者我在查询中误解了一

下面的代码是一个工厂类,它提供了实现了GraphTypeAttribute的IGraph类型的对象。在GraphFactory的静态构造函数中,通过使用Linq收集工厂要交付的适当类来构建一个列表。通常没有Linq的情况下,我会有一堆循环,如果有,那么可以用合适的try-catch块轻松包装由于所有内容都塞进了一个查询中,现在我对如何在这里实现适当的异常处理有点困惑

所以我的问题是/是

  • 处理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());
    }
}