gpt4 book ai didi

c# - 使用泛型访问基本抽象类方法中的子类对象

转载 作者:太空宇宙 更新时间:2023-11-03 11:19:39 25 4
gpt4 key购买 nike

我现有的类结构。

AbstractTradeBaseClass -> AbstractTradeClass -> ConcreteTradeClass。

我正在使用 DataAnnotations 和 IDataErrorInfo 在我的 WPF 应用程序中验证我的模型。我已将 IDataErrorInfo 方法移至 AbstractTradeBaseClass,以便所有从基类继承的类都可以使用我。

这是通过使用 Linq 动态读取属性来完成的。

AbstractTradeBaseClass.cs

 public abstract class TradeBaseModel<T> : INotifyPropertyChanged, IDataErrorInfo
{
#region INotifyPropertyChanged Members

public event PropertyChangedEventHandler PropertyChanged;

public void OnPropertyChanged( string propertyName )
{
if ( PropertyChanged != null )
{
PropertyChanged( this, new PropertyChangedEventArgs( propertyName ) );
}
}

#endregion

# region Getter/Validator members for Annotations
private static readonly Dictionary<string, Func<T, object>>
propertyGetters = typeof( T ).GetProperties()
.Where( p => GetValidations( p ).Length != 0 )
.ToDictionary( p => p.Name, p => GetValueGetter( p ) );

private static readonly Dictionary<string, ValidationAttribute[]> validators =
typeof( T ).GetProperties()
.Where( p => GetValidations( p ).Length != 0 )
.ToDictionary( p => p.Name, p => GetValidations( p ) );

private static ValidationAttribute[] GetValidations( PropertyInfo property )
{
return ( ValidationAttribute[] )property.GetCustomAttributes( typeof( ValidationAttribute ), true );
}

private static Func<T, object> GetValueGetter( PropertyInfo property )
{
var instance = Expression.Parameter( typeof( T ), "i" );
var cast = Expression.TypeAs( Expression.Property( instance, property ), typeof( object ) );
return ( Func<T, object> )Expression.Lambda( cast, instance ).Compile();
}
# endregion

#region IDataErrorInfo Members

public string Error
{
get
{
var errors = from i in validators
from v in i.Value
where !v.IsValid( propertyGetters[i.Key]( **( T )ModelToValidate()** ) )
select v.ErrorMessage;
return string.Join( Environment.NewLine, errors.ToArray() );
}
}

protected Dictionary<string, string> _errors = new Dictionary<string, string>();
public IDictionary<string, string> Errors
{
get { return _errors; }
}

public string this[string columnName]
{
get
{
string errorMessage = string.Empty;
this.Errors.Remove( columnName );

//string errorMessage = string.Empty;
//switch(columnName)
//{
// case "Range":
// if ( Range > 15 )
// {
// errorMessage = "Out of Range, should be less than 15";
// }
// break;
//}

//return errorMessage;

if ( propertyGetters.ContainsKey( columnName ) )
{
var value = propertyGetters[columnName]( **( T )ModelToValidate()** );
var errors = validators[columnName].Where( v => !v.IsValid( value ) )
.Select( v => v.ErrorMessage ).ToArray();

string error = string.Join( Environment.NewLine, errors );
this.OnPropertyChanged( "Error" );

if ( !string.IsNullOrEmpty( error ) )
{
this.Errors.Add( columnName, error );
}

return error;
}

return string.Empty;

}
}

public abstract object ModelToValidate(); -- ***Gets the child object here, overridden in the child class to return the child object, -- is there a better way to do this using Generics ??***

#endregion
}

抽象贸易类

 public abstract class TradeClassBase<T> : TradeBaseModel<T>
{
public string EmptyString
{
get { return string.Empty; }
}
}

具体贸易类

public class CashFlowTrade : TradeClassBase<CashFlowTrade>
{
private int range;
[RangeAttribute(0,10, ErrorMessage="Out of Range, Range should be less than 15")]
public int Range
{
get
{
return this.range;
}
set
{
if ( this.range != value )
{
this.range = value;
this.OnPropertyChanged( "Range" );
}
}
}

public override object ModelToValidate()
{
return this;
}

}

有没有更好的方法来代替使用抽象方法并在子类中覆盖它以传递实际的子类对象并将其转换为类型 T。用法在上面的代码中以粗体显示。

如果有办法可以将子类对象向下传递给基类,我就可以使用实际的子类对象本身来执行验证操作。


更新的工作代码使用类约束 T 并使用类型转换运算符,如下所示。

    public abstract class TradeBaseModel<T> : INotifyPropertyChanged, IDataErrorInfo
where T : class

用类型转换替换对抽象方法的调用。

 if ( propertyGetters.ContainsKey( columnName ) )
{
var value = propertyGetters[columnName]( this as T );

最佳答案

是的……直接用这个。即使在抽象类中,您也可以访问此引用。唯一不能使用它的地方是在静态方法中。

编辑:

要强制执行类型检查,您可以在 T 上添加约束:

public abstract class TradeBaseModel<T> : INotifyPropertyChanged, IDataErrorInfo where T: TradeBaseModel<T>

编辑 2:

总结 Kans 在下面的评论,这还不够:此转换支持从 T 到基类型的隐式类型转换,而从基类型到 T 的转换是必需的。唯一的解决方案似乎是在上面的代码中使用 T 作为运算符,为此,T 必须是一个类(如果添加了上述约束就可以了)。

关于c# - 使用泛型访问基本抽象类方法中的子类对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11450590/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com