2016-07-07 64 views
0

我有一个Dictionary,它将枚举值作为键并返回一个对象作为值。对象构造函数涉及调用需要很长时间并消耗大量内存的方法。现在,字典中的每个可能的对象都会被创建,即使只需要一个对象。有没有办法只创建键指定的对象?Make对象的字典只创建指定键的对象

private DataPreparer SetUpOuDataPreparer() 
{ 
    Scope = _activeDirectoryScope.Context; 
    var activeDirectorySearcher = new ActiveDirectorySearcher(
     _activeDirectoryScope); 
    var ouDataPreparers = new Dictionary<QueryType, DataPreparer> 
    { 
     [OuComputers] = new DataPreparer 
     { 
      Data = activeDirectorySearcher.GetOuComputerPrincipals(), 
      Attributes = DefaultComputerAttributes 
     }, 
     [OuGroups] = new DataPreparer 
     { 
      Data = activeDirectorySearcher.GetOuGroupPrincipals(
       CancellationToken), 
      Attributes = DefaultGroupAttributes 
     }, 
     [OuUsers] = new DataPreparer 
     { 
      Data = activeDirectorySearcher.GetOuUserPrincipals(), 
      Attributes = DefaultUserAttributes 
     }, 
     [OuUsersDirectReports] = new DataPreparer 
     { 
      Data = activeDirectorySearcher.GetOuUsersDirectReports(
       CancellationToken), 
      Attributes = DefaultUserDirectReportsAttributes 
     }, 
     [OuUsersGroups] = new DataPreparer 
     { 
      Data = activeDirectorySearcher.GetOuUsersGroups(
       CancellationToken), 
      Attributes = DefaultUserGroupsAttributes 
     } 
    }; 
    return ouDataPreparers[QueryType]; 
} 

也就是说方法创建所有五个DataPreparer S,其中的每一个具有在ActiveDirectorySearcher昂贵的方法调用。我想以某种方式只创建由QueryType密钥指定的DataPreparer,最好不使用switchif/else。为了更好的格式化/风格,我将其从那些更改为Dictionary

+0

为什么要使用字典呢?为什么不只是一个带有switch语句的工厂方法方法? –

+0

@AntP我在问题中提到我想避免切换,如果出于文体原因。 –

+0

我不确定他们是什么“风格的原因”,但创建了一个你只需要一个对象的集合,因为这个工作的正确工具看起来不太漂亮,这对我来说似乎有点落后。 –

回答

1

您可以更改的类型是Func<DataPreparer>所以你会得到一个值的工厂,只是后来调用它:

var ouDataPreparers = new Dictionary<QueryType, Func<DataPreparer>> 
{ 
    [OuComputers] =() => new DataPreparer 
    { 
     Data = activeDirectorySearcher.GetOuComputerPrincipals(), 
     Attributes = DefaultComputerAttributes 
    }, 

    return ouDataPreparers[QueryType](); 
} 

以这样的方式,对象被创建的每个您的查询的时间。

如果你想创建它一次,并保持相同的情况下像一个单身,你可以使用Lazy<DataPreparer>

var ouDataPreparers = new Dictionary<QueryType, Lazy<DataPreparer>> 
{ 
    [OuComputers] = new Lazy<DataPreparer>(() => new DataPreparer 
    { 
     Data = activeDirectorySearcher.GetOuComputerPrincipals(), 
     Attributes = DefaultComputerAttributes 
    }), 

    return ouDataPreparers[QueryType].Value; 
} 
+0

这两个选项都会导致警告“隐式捕获的闭包:this”。思考? –

+0

我想这是'DefaultComputerAttributes',它可能是lambda表达式中使用的对象的变量。 –

+0

所有赋给'Attributes'的值都是'static readonly Array's。这个警告也只出现在'OuUsers'和'OuComputers'条目中(只有两个不带'CancellationToken'参数)。 –

6

我会考虑在您的DataPreparer类中使用Lazy<T>作为您的Data属性。这样,它只会在实际需要时调用activeDirectorySearcher.GetOuGroupPrincipals,而不是在创建时一次。