使对象字典仅创建指定键的对象

时间:2016-07-07 12:44:18

标签: c# dictionary

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

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,每个ActiveDirectorySearcher都有一个昂贵的方法调用DataPreparer。我想以某种方式仅创建QueryType密钥指定的switch,最好不要使用if/elseDictionary。为了更好的格式/样式,我从那些更改为{{1}}。

2 个答案:

答案 0 :(得分:6)

我会考虑在您的Lazy<T>课程中使用Data DataPreparer属性。这样,它只会在实际需要时调用activeDirectorySearcher.GetOuGroupPrincipals,而不是在创建时立即调用。{/ p>

答案 1 :(得分: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;
}