tôi đã thực hiện các bài kiểm tra NUnit sau đó sử dụng phản xạ để kiểm tra việc thực hiện. Hy vọng rằng bạn có thể thích ứng khi cần thiết.
Tôi nghi ngờ nó sẽ không xử lý các phương pháp quá tải tốt, nhưng nó đủ cho những gì tôi muốn.
(Cảm nhận hoan nghênh)
/// <summary>
/// Use on a (possibly abstract) method or property to indicate that all subclasses must provide their own implementation.
///
/// This is stronger than just abstract, as when you have
///
/// A { public abstract void Method()}
/// B: A { public override void Method(){} }
/// C: B {}
///
/// C will be marked as an error
/// </summary>
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Method)]
public class AllSubclassesMustOverrideAttribute : Attribute
{
}
[TestFixture]
public class AllSubclassesMustOverrideAttributeTest
{
[Test]
public void SubclassesOverride()
{
var failingClasses = new List<string>();
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
{
try
{
foreach (var type in assembly.GetTypes())
{
foreach (var methodInfo in type.GetMethods().Where(m => m.HasAttributeOfType<AllSubclassesMustOverrideAttribute>()))
{
foreach (var subClass in type.ThisTypeAndSubClasses())
{
var subclassMethod = subClass.GetMethod(methodInfo.Name);
if (subclassMethod.DeclaringType != subClass)
{
failingClasses.Add(string.Format("Class {0} has no override for method {1}", subClass.FullName, methodInfo.Name));
}
}
}
foreach (var propertyInfo in type.GetProperties().Where(p => p.HasAttributeOfType<AllSubclassesMustOverrideAttribute>()))
{
foreach (var subClass in type.ThisTypeAndSubClasses())
{
var subclassProperty = subClass.GetProperty(propertyInfo.Name);
if (subclassProperty.DeclaringType != subClass)
{
failingClasses.Add(string.Format("Class {0} has no override for property {1}", subClass.FullName, propertyInfo.Name));
}
}
}
}
}
catch (ReflectionTypeLoadException)
{
// This will happen sometimes when running the tests in the NUnit runner. Ignore.
}
}
if (failingClasses.Any())
{
Assert.Fail(string.Join("\n", failingClasses));
}
}
}
Nó sử dụng các phương pháp khuyến nông sau
public static bool HasAttributeOfType<T>(this ICustomAttributeProvider provider)
{
return provider.GetCustomAttributes(typeof(T), false).Length > 0;
}
public static IEnumerable<Type> ThisTypeAndSubClasses(this Type startingType)
{
var types = new List<Type>();
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
{
try
{
foreach (var type in assembly.GetTypes())
{
if (startingType.IsAssignableFrom(type))
{
types.Add(type);
}
}
}
catch (ReflectionTypeLoadException)
{
// Some assembly types are unable to be loaded when running as nunit tests.
// Move on to the next assembly
}
}
return types;
}
Nguồn
2015-10-16 14:10:16
Chừng một số lớp bê tông trong cây thừa kế đã thực hiện phương pháp trừu tượng, tại sao bạn sẽ quan tâm nếu một đứa trẻ của lớp bê tông đó dựa vào việc thực hiện của cha mẹ? –
Tôi đến muộn nhưng tôi có cùng một vấn đề.Tôi muốn có một vòng loại 'abstract trừu tượng' để buộc mọi lớp dẫn xuất phải thực hiện hàm nhưng ngăn chặn mã của classe hoàn toàn rơi trở lại việc thực thi lớp cha. 'Clone()' là một ví dụ tốt. Trường hợp của tôi giống như 'ToString()'. Một cái gì đó chung chung nhưng khác biệt cho mỗi lớp. –
Thực ra điều này phải xảy ra thường xuyên hơn (hoặc tôi thiếu một cái gì đó). –