Skip to content

Instantly share code, notes, and snippets.

@sliekens
Last active May 14, 2019 23:04
Show Gist options
  • Save sliekens/020efcd4503267ea9c055014de01362c to your computer and use it in GitHub Desktop.
Save sliekens/020efcd4503267ea9c055014de01362c to your computer and use it in GitHub Desktop.
Design for inheritance
using System;
using System.Linq;
using System.Reflection;
using Xunit;
namespace YourLibName.Tests.PatternsAndPractices
{
public class DesignedForInheritanceTest
{
public DesignedForInheritanceTest()
{
_assembly = Assembly.Load("YourLibName");
}
private readonly Assembly _assembly;
[Fact]
public void EveryExportedClass_ShouldBeInheritableOrSealed()
{
var classes = _assembly.ExportedTypes.Where(type => type.IsClass).ToList();
foreach (var type in classes)
{
if (type.IsAbstract)
{
continue;
}
if (type.IsSealed)
{
continue;
}
if (type.GetCustomAttribute<InheritableAttribute>() is object)
{
continue;
}
throw new ApplicationException(
$"Type '{type}' is public but not abstract, seal it or mark it as [Inheritable].");
}
}
}
}
using System;
namespace YourLibName
{
// This class is abstract so it will PASS the test
public abstract class AbstractClass
{
}
// This class is static so it will PASS the test
public static class StaticClass
{
}
// This class is internal so it will PASS the test
internal class InternalClass
{
}
// This class is marked Inheritable so it will PASS the test
[Inheritable]
public class InheritableClass
{
}
// This class shows no design for inheritance so it will FAIL the test
public class Foo
{
}
}
using System;
namespace YourLibName
{
/// <summary>Use this attribute to mark non-abstract classes that are designed to be inheritable.</summary>
[AttributeUsage(AttributeTargets.Class, Inherited = false)]
internal sealed class InheritableAttribute : Attribute
{
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment