C# 运行时用new关键字标记为空的属性,但基本属性正确
关于派生类中带有属性的C# 运行时用new关键字标记为空的属性,但基本属性正确,c#,serialization,polymorphism,overriding,new-operator,C#,Serialization,Polymorphism,Overriding,New Operator,关于派生类中带有属性的new关键字,我有很多问题,可能是误解。大多数文档都涉及衍生方法的new。例如: [DataContract] [KnownType(typeof(PostCategory))] public class BaseCategory : IEquatable<BaseCategory> { //... /// <summary> /// Enables access to child categories (immediate one
new
关键字,我有很多问题,可能是误解。大多数文档都涉及衍生方法的new
。例如:
[DataContract]
[KnownType(typeof(PostCategory))]
public class BaseCategory : IEquatable<BaseCategory>
{
//...
/// <summary>
/// Enables access to child categories (immediate ones). Filled in by data access provider. Not serializable.
/// </summary>
public SortedDictionary<string, BaseCategory> Children { get; set; }
//...
}
[DataContract]
[KnownType(typeof(BaseCategory))]
public class PostCategory : BaseCategory
{
//...
public new SortedDictionary<string, PostCategory> Children { get; set; }
//...
}
[DataContract]
[知识类型(类型(后分类))]
公共类基类:IEquatable
{
//...
///
///允许访问子类别(直接类别)。由数据访问提供程序填写。不可序列化。
///
公共排序字典子项{get;set;}
//...
}
[数据合同]
[知识类型(类型(基本类别))]
公共类后类别:基本类别
{
//...
公共新SortedDictionary子项{get;set;}
//...
}
然后,在我的数据存储库实现中,我有一个通用实现,用于派生自BaseCategory的所有类。我这样做:
public class CachedXmlCategorizationProvider<T> : ICategorizationRepository<T> where T : BaseCategory, new()
{
private readonly ICacheProvider _cacheProvider = AppServices.Cache;
private readonly string _file = Path.Combine(XmlProvider.DataStorePhysicalPath, typeof (T).Name, "categorization.xml");
private SortedDictionary<string, T> _dictionary;
//...
private SortedDictionary<string, T> LoadFromDatastore()
{
if (!DefaultsExist())
{
return CreateDefaults();
}
var dcs = new DataContractSerializer(typeof (SortedDictionary<string, T>));
XmlDictionaryReader reader =
XmlDictionaryReader.CreateTextReader(new FileStream(_file, FileMode.Open, FileAccess.Read),
new XmlDictionaryReaderQuotas());
_dictionary = (SortedDictionary<string, T>) dcs.ReadObject(reader, true);
/* HERE! Apparently this fills in the Children property of the base class */
// fill in Children
foreach (var pair in _dictionary)
{
pair.Value.Children = GetChildren(pair.Value.Id);
}
reader.Close();
return _dictionary;
}
//...
}
公共类CachedXmlCategorizationProvider:ICategorizationRepository其中T:BaseCategory,new()
{
私有只读ICacheProvider\u cacheProvider=AppServices.Cache;
私有只读字符串_file=Path.Combine(XmlProvider.DataStorePhysicalPath,typeof(T).Name,“categorization.xml”);
私人分类词典;
//...
私有SortedDictionary LoadFromDatastore()
{
如果(!DefaultsExist())
{
返回CreateDefaults();
}
var dcs=新的DataContractSerializer(typeof(SortedDictionary));
XmlDictionaryReader阅读器=
XmlDictionaryReader.CreateTextReader(新文件流(_file,FileMode.Open,FileAccess.Read),
新的XmlDictionaryReaderQuotas());
_dictionary=(SortedDictionary)dcs.ReadObject(reader,true);
/*这里!显然这填充了基类的Children属性*/
//填写儿童
foreach(字典中的var对)
{
pair.Value.Children=GetChildren(pair.Value.Id);
}
reader.Close();
返回字典;
}
//...
}
当我试图在运行时访问特定的后分类
实例的Children
属性时,它是null
,并且base.Children
被设置为由GetChildren()
方法设置的正确的子字典
问题是,我的代码依赖于检查PostCategory.Children实例,因为它为null,所以我的代码失败了
实现我想要的(拥有一个基类并更改派生类中属性的类型)的正确方法是什么?对于
new
关键字的继承与virtual
override
成员的作用方式不同,因为它根本不起作用。如果通过对基类的引用访问该成员,则会访问基类的成员,并完全绕过隐藏的成员。在正确继承的情况下,如果派生类中的任何一个重写了基成员,则这种调用将继续下去
如果需要正确的行为,则需要将基本属性设置为虚拟属性
,并在派生类中重写它
似乎您正在尝试使派生类型更具体。这可能通过使用接口和来实现。我无法使用虚拟覆盖组合更改基本属性的类型。我们将调查协方差。。