来自字符串类型名称的强类型对象(C#)

时间:2010-01-30 16:33:38

标签: c# reflection

如果您查看以下代码,您(希望)会看到我想要实现的目标。基本上这段代码确实:

  • 查询通用storag项目(它们将其类型存储为字符串)
  • 如果该项是SearchCriteria的子类,请创建正确的实例
  • 将实例添加到列表中(SearchCriteria是超类)

当然,不是很优雅的伪开关案例,我必须根据我创建的所有不同标准进行更新。

所以,我的问题是,是否有一种“通用”方法来创建一个强类型的实例,使用字符串作为该类型的“源”。

我知道我可以使用Reflection来创建一个实例,但这是一个object类型,所以我无法将它添加到列表中。哦,只是有了一个想法...使用反射创建对象,将其强制转换为超类型(SearchCrit),添加到列表中。真正的类型应该仍然是“正确的子类型”,我希望......

会尝试一下,并用结果更新这篇文章。有更好的想法吗?

克里斯

   private IList<SearchCriteria> _searchCriteriaAll;
    public IList<SearchCriteria> SearchCriteriaAll
    {
        get
        {
            if (_searchCriteriaAll == null)
            {
                _searchCriteriaAll = new List<SearchCriteria>();
                var tN = typeof (SearchCriteria).ToString();
                foreach (var o in DataStorage.LinkedObjects)
                {
                    if (tN.StartsWith(o.TypeName))
                    {
                        if (o.TypeName == typeof(StringSearchCriteria).ToString())
                            _searchCriteriaAll.Add(new StringSearchCriteria(o));
                    }
                }
            }
            return _searchCriteriaAll;
        }
    }

修改

感谢您的提示,“正确”的方式绝对是工厂模式。我会调查一下。现在,我使用这个hack,因为子类是如此之小,我不想为每一个工厂..(而这个地方目前是唯一具有这种“花哨”特征的地方)

   private IList<SearchCriteria> _searchCriteriaAll;
    public IList<SearchCriteria> SearchCriteriaAll
    {
        get
        {
            if (_searchCriteriaAll == null)
            {
                _searchCriteriaAll = new List<SearchCriteria>();
                var tN = typeof (SearchCriteria).ToString();
                foreach (var o in DataStorage.LinkedObjects)
                {
                    if (tN.StartsWith(o.TypeName))
                    {
                        var newO = Activator.CreateInstance(typeof(SearchCriteria).Assembly.FullName, o.TypeName);
                        var newCrit = newO.Unwrap() as SearchCriteria;
                        newCrit.DataStorage = o;
                        _searchCriteriaAll.Add(newCrit);
                    }
                }
            }
            return _searchCriteriaAll;
        }
    }

3 个答案:

答案 0 :(得分:3)

泛化与反思并不能成为好朋友。这里更简单的方法是使用非通用列表接口:

_searchCriteriaAll = new List<SearchCriteria>();
IList list = (IList) _searchCriteriaAll;
...
Type type = typeof(SearchCriteria).Assembly.GetType(o.TypeName);
list.Add(Activator.CreateInstance(type));

(其中o.TypeName包含命名空间信息,但不必是程序集限定的)

这仍然是运行时类型安全的(如果它是错误的,它将在运行时抛出),并仍然调整相同的列表。

另请注意,我们只能通过Assembly直接查看Assembly.GetType()内部。

答案 1 :(得分:0)

我说你正在寻找Factory Method Pattern

有一个C#样本here - 第一个链接更好地解释了模式,第二个链接是适合您的语言。

答案 2 :(得分:0)

我并不完全清楚你想要实现的目标,但你可以从这样的字符串中创建一个Type:

var t = Type.GetType(typeName);

如果要检查它是否是正确的子类型,可以使用IsAssignableFrom方法。