How to check whether an interface's MethodInfo is a "new" method - c#

I'm trying to use reflection to retrieve a list of all methods of an interface + its base interfaces.
So far I have this:
var methods = type.GetMethods().Concat(
type.GetInterfaces()
.SelectMany(#interface => #interface.GetMethods()));
I'd like to be able to filter out methods that shadow methods declared in base interfaces, i.e., "new" methods:
public interface IBaseInterface
{
string Method();
}
public interface IInterfaceWithNewMethod : IBaseInterface
{
new string Method();
}
With my current code, the result includes both methods - I'd like to retrieve IInterfaceWithMethod.Method only and filter out IBaseInterface.Method.
Fiddle: https://dotnetfiddle.net/fwVeLS
PS: If it helps, you can assume I have access to a concrete instance of the derived interface. The type of that instance will only be known at runtime (it's a dynamic proxy).

Well, a dirty way might be to manually check if the method signatures match.
A method to check signatures might look like this:
public static bool HasSameSignature(MethodInfo potentiallyHidingMethod, MethodInfo baseMethod)
{
//different name, therefore not same signature
if (potentiallyHidingMethod.Name != baseMethod.Name)
return false;
//now we check if they have the same parameter types...
var potentiallyHidingMethodParameters = potentiallyHidingMethod.GetParameters();
var baseMethodParameters = baseMethod.GetParameters();
//different number of parameters, therefore not same signature
if (potentiallyHidingMethodParameters.Length != baseMethodParameters.Length)
return false;
for (int i = 0; i < potentiallyHidingMethodParameters.Length; i++)
{
//if a parameter type doesn't match, it's not the same signature
if (potentiallyHidingMethodParameters[i].ParameterType != baseMethodParameters[i].ParameterType)
return false;
}
//if we've gotten this far, they have the same name and parameters,
//therefore, it's the same signature.
return true;
}
Then it's a matter of checking the derived interface methods to see if they hide (or match the signature of) any of the base interface methods:
Type type = typeof(IInterfaceWithNewMethod);
var potentiallyHidingMethods = type.GetMethods();
var baseTypeMethods =type.GetInterfaces()
.SelectMany(#interface => #interface.GetMethods());
var hidingMethods = potentiallyHidingMethods
.Where(hiding => baseTypeMethods.Any(baseMethod => HasSameSignature(hiding, baseMethod)));
Note, this is a bit of a naive implementation. I wouldn't be surprised if there's a simpler way or corner cases that this doesn't cover.
EDIT: Slightly misunderstood the desired output. Using the code above, this will give you all the base interface methods, plus the derived interface methods, but filtered out any base interface methods that were hidden by the derived interface:
var allMethodsButFavouringHiding = potentiallyHidingMethods.Concat(
baseTypeMethods.Where(baseMethod => !potentiallyHidingMethods.Any(potentiallyhiding => HasSameSignature(potentiallyhiding, baseMethod))));
EDITx2: I did a test given the following interfaces:
public interface IBaseInterface
{
string BaseMethodTokeep();
string MethodToHide();
string MethodSameName();
}
public interface IInterfaceWithNewMethod : IBaseInterface
{
new string MethodToHide();
new string MethodSameName(object butDifferentParameters);
string DerivedMethodToKeep();
}
This results with a collection of MethodInfo:
MethodToHide (IInterfaceWithNewMethod)
MethodSameName (IInterfaceWithNewMethod)
DerivedMethodToKeep (IInterfaceWithNewMethod)
BaseMethodTokeep (IBaseInterface)
MethodSameName (IBaseInterface)
So it keeps any base interface methods that aren't hidden, any derived interface methods (that are hiding or otherwise), and honours any signature changes (that is, different parameters which would result in not hiding).
EDITx3: Added another test with overloads:
public interface IBaseInterface
{
string MethodOverloadTest();
string MethodOverloadTest(object withParam);
}
public interface IInterfaceWithNewMethod : IBaseInterface
{
new string MethodOverloadTest();
}
With results of:
MethodOverloadTest() for IInterfaceWithNewMethod
MethodOverloadTest(object) for IBaseInterface

I ended up using a mix of Chris Sinclair and Thomas Levesque's answers.
It's a bit more extensive, but it's more robust.
More importantly, I think it's much easier to read and reason about, which is a top priority when dealing with reflection. We all know how easy it is for reflection code to become complex and a whole mess...
internal static class TypeExtensions
{
/// <summary>
/// Gets a collection of all methods declared by the interface <paramref name="type"/> or any of its base interfaces.
/// </summary>
/// <param name="type">An interface type.</param>
/// <returns>A collection of all methods declared by the interface <paramref name="type"/> or any of its base interfaces.</returns>
public static IEnumerable<MethodInfo> GetInterfaceMethods(this Type type)
{
var allMethods = type.GetMethods().Concat(
type.GetInterfaces()
.SelectMany(#interface => #interface.GetMethods()));
return allMethods.GroupBy(method => new Signature(method))
.Select(SignatureWithTheMostDerivedDeclaringType);
}
private static MethodInfo SignatureWithTheMostDerivedDeclaringType(IGrouping<Signature, MethodInfo> group)
{
return group.Aggregate(
(a, b) => a.DeclaringType.IsAssignableFrom(b.DeclaringType) ? b : a);
}
private sealed class Signature
{
private readonly MethodInfo method;
public Signature(MethodInfo method)
{
this.method = method;
}
public override bool Equals(object obj)
{
var that = obj as Signature;
if (that == null)
return false;
//different names, therefore different signatures.
if (this.method.Name != that.method.Name)
return false;
var thisParams = this.method.GetParameters();
var thatParams = that.method.GetParameters();
//different number of parameters, therefore different signatures
if (thisParams.Length != thatParams.Length)
return false;
//different paramaters, therefore different signatures
for (int i = 0; i < thisParams.Length; i++)
if (!AreParamsEqual(thisParams[i], thatParams[i]))
return false;
return true;
}
/// <summary>
/// Two parameters are equal if they have the same type and
/// they're either both "out" parameters or "non-out" parameters.
/// </summary>
private bool AreParamsEqual(ParameterInfo x, ParameterInfo y)
{
return x.ParameterType == y.ParameterType &&
x.IsOut == y.IsOut;
}
public override int GetHashCode()
{
int hash = 37;
hash = hash*23 + method.Name.GetHashCode();
foreach (var p in method.GetParameters())
{
hash = hash*23 + p.ParameterType.GetHashCode();
hash = hash*23 + p.IsOut.GetHashCode();
}
return hash;
}
}
}

Related

How do I use reflection to execute an explicitly-implemented static abstract method

Given the following interface that forces classes to implement a static method...
public interface IMyInterface<T>
{
static abstract int GetNumber();
}
And two classes that both have two implementations of IMyInterfacee<T>
public class MyClass1 : IMyInterface<Company>, IMyInterface<Person>
{
static int IMyInterface<Company>.GetNumber() => 1;
static int IMyInterface<Person>.GetNumber() => 2;
}
public class MyClass2 : IMyInterface<Company>, IMyInterface<Person>
{
static int IMyInterface<Company>.GetNumber() => 3;
static int IMyInterface<Person>.GetNumber() => 4;
}
When I have a method in a consuming class like this
public int GetNumbers(Type classType, Type genericType)
{
Type interfaceType = typeof(IMyInterface<>).MakeGenericType(genericType);
return ??????
}
How would I implement GetNumbers so that I can call it like so
GetNumbers(typeof(MyClass1), typeof(Company)); // returns 1
GetNumbers(typeof(MyClass1), typeof(Person)); // returns 2
GetNumbers(typeof(MyClass2), typeof(Company)); // returns 3
GetNumbers(typeof(MyClass2), typeof(Person)); // returns 3
You can use interface mapping (Type.GetInterfaceMap) to find the method which implements the interface:
int GetNumbers(Type classType, Type genericType)
{
Type interfaceType = typeof(IMyInterface<>).MakeGenericType(genericType);
// todo - check that class implements interface
var interfaceMapping = classType.GetInterfaceMap(interfaceType);
MethodInfo? methodInfo = null;
for (int i = 0; i < interfaceMapping.InterfaceMethods.Length; i++)
{
var sourceMethod = interfaceMapping.InterfaceMethods[i];
// simple predicate to find by name
// possibly check that parameters are empty and return type is int
if (sourceMethod.Name.Equals(nameof(IMyInterface<object>.GetNumber), StringComparison.Ordinal))
{
methodInfo = interfaceMapping.TargetMethods[i];
break;
}
}
if (methodInfo is null)
{
throw new Exception("Should not happen");
}
return (int)methodInfo.Invoke(null, null);
}
I can't write a regular comment below Guru Stron's answer due to a lack of rep, but GetInterfaceMap is currently broken for interfaces that contain static abstract or static virtual members: Passing the type of such an interface unconditionally throws a VerificationException. See dotnet/runtime#73658.
Additionally, with there being two other reflection issues of interfaces with static abstracts linked to it, it seems that most of the reflection stack just doesn't work at all with such interface types. In that light, the only good answer I can give is "You just can't do this (until it's fixed (hopefully in a .NET 7 servicing update, but I'm not holding my breath))".

How to find the smallest assignable type in two types (duplicate)? [duplicate]

This question already has answers here:
How to find the minimum covariant type for best fit between two types?
(3 answers)
Closed 9 years ago.
Here're two extension methods for use
public static Type FindInterfaceWith(this Type type1, Type type2) {
// returns most suitable common implemented interface
}
public static Type FindBaseClassWith(this Type type1, Type type2) {
// returns most derivative of common base class
}
FindInterfaceWith returns null if they don't have common implemented interface.
FindBaseClassWith returns System.Object if they have no more derivative common base class.
FindBaseClassWith returns null if one of parameters was an interface.
Both they return null if any of parameter was null.
And the signature of method in finally solution would be like:
public static Type FindAssignableWith(this Type type1, Type type2) {
// what should be here?
}
Reflection and Linq are restricted to use, except there are no other way.
Are there good ways to find the best fit of common type between type1 and type2?
Or are there something better to achieve this?
update:
By my personal understanding, because of the ability to implement multiple interfaces with a class, the FindInterfaceWith could possibly need to call FindBaseClassWith internally; otherwise the best choice of type would be undecidable.
If this supposition was correct, then the FindInterfaceWith becomes a redundant method; because of the only difference between FindInterfaceWith and FindAssignableWith is:
FindInterfaceWith returns null if there was a best choice of class; while FindAssignableWith returns the exact class directly.
Otherwise, they both return a best choice of interface.
This is about saying the original assumption was irrational. That is, FindInterfaceWith cannot be implemented if FindAssignableWith is not.
Here is my implementation:
FindAssignableWith, FindBaseClassWith and FindInterfaceWith implementations
// provide common base class or implemented interface
public static Type FindAssignableWith(this Type typeLeft, Type typeRight)
{
if(typeLeft == null || typeRight == null) return null;
var commonBaseClass = typeLeft.FindBaseClassWith(typeRight) ?? typeof(object);
return commonBaseClass.Equals(typeof(object))
? typeLeft.FindInterfaceWith(typeRight)
: commonBaseClass;
}
// searching for common base class (either concrete or abstract)
public static Type FindBaseClassWith(this Type typeLeft, Type typeRight)
{
if(typeLeft == null || typeRight == null) return null;
return typeLeft
.GetClassHierarchy()
.Intersect(typeRight.GetClassHierarchy())
.FirstOrDefault(type => !type.IsInterface);
}
// searching for common implemented interface
// it's possible for one class to implement multiple interfaces,
// in this case return first common based interface
public static Type FindInterfaceWith(this Type typeLeft, Type typeRight)
{
if(typeLeft == null || typeRight == null) return null;
return typeLeft
.GetInterfaceHierarchy()
.Intersect(typeRight.GetInterfaceHierarchy())
.FirstOrDefault();
}
// iterate on interface hierarhy
public static IEnumerable<Type> GetInterfaceHierarchy(this Type type)
{
if(type.IsInterface) return new [] { type }.AsEnumerable();
return type
.GetInterfaces()
.OrderByDescending(current => current.GetInterfaces().Count())
.AsEnumerable();
}
// interate on class hierarhy
public static IEnumerable<Type> GetClassHierarchy(this Type type)
{
if(type == null) yield break;
Type typeInHierarchy = type;
do
{
yield return typeInHierarchy;
typeInHierarchy = typeInHierarchy.BaseType;
}
while(typeInHierarchy != null && !typeInHierarchy.IsInterface);
}
Remark regarding FindInterfaceWith implementation
Any interfaces that implements either IEnumerable or IEnumerable<T> will be selected before others, what I considered not to be correct
Open ended question of FindInterfaceWith
c# allow multiple interfaces to be implemented in one class, in this case first one of interfaces will be returned by FindInterfaceWith, because there is no way how to know which of interfaces IA or IB are preferable in general in following sample
Interfaces and classes hierarchy
public interface IBase {}
public interface ISomething {}
public interface IDerivied: IBase {}
public interface IDeriviedRight: IDerivied {}
public interface IDeriviedLeft: IDerivied, IDisposable {}
public class AnotherDisposable: IDisposable {
public void Dispose() {
}
}
public class DeriviedLeft: IDeriviedLeft {
public void Dispose() {
}
}
public class SubDeriviedLeft: DeriviedLeft {}
public class SecondSubDeriviedLeft: DeriviedLeft {}
public class ThirdSubDeriviedLeft: DeriviedLeft, ISomething {}
public class Another {}
public class DeriviedRight: IDeriviedRight {}
Test cases
And set of test cases using NUnit assertions:
FindBaseClassWith assertions example
// FindBaseClassWith returns null if one of parameters was an interface.
// FindBaseClassWith return null if any of parameter was null.
Assert.That(typeof(DeriviedLeft).FindBaseClassWith(typeof(DeriviedLeft)), Is.EqualTo(typeof(DeriviedLeft)));
FindInterfaceWith assertions example
// FindInterfaceWith returns null if they don't have common implemented interface.
// FindBaseClassWith return null if any of parameter was null.
Assert.That(typeof(DeriviedLeft).FindInterfaceWith(typeof(DeriviedLeft)), Is.EqualTo(typeof(IDeriviedLeft)));
FinAssignableWith assertions example
Assert.That(typeof(DeriviedLeft).FindAssignableWith(typeof(DeriviedLeft)), Is.SameAs(typeof(DeriviedLeft)));
Discussion at CodeReview
Review of this answer at codereview.stackexchange.com
ps:
Full sources available [here]
Oh, yay, I get to show off something I recently wrote for something else! :)
Caveat: This code is not the most efficient in the world, and it's VERY poorly commented - it was for a personal project, and I already knew how it worked - but I think it'll get you what you're after...
The method you'd be most interested in would be
public static Tuple<Type, IEnumerable<Type>> GetCommonBases(Type left, Type right)
The Tuple returned is <common base class, (list of common interfaces)>
A quick summary: this class, when given a type, does the following:
Reverse walks up the given type until it hits no more base types, pushing each into a 'working stack'
Pops each base type off the working stack, inserting it into a tree-like structure; If the type implements any interfaces, it adds nodes for those interface types as well
the helper method GetCommonBases creates one of these TypeTree structures for the first type, then 'merges' in the type tree for the other given type: it does so by walking down common base types until it finds a point where you have a common base type between the two types, at which point two branches of the tree are formed. It then "drills down" to each type from the root (i.e., System.Object), then finds the first point of deviation. The parent of this point of deviation is the Common base type.
The interfaces part relies on the definition of Interfaces, which "inherits" any Interface nodes for any ancestor. The GetCommonBases method pulls a list of any interfaces implemented by the two passed in types and returns an intersection of these two lists - that is, a set of interfaces that both passed in types implement.
the method then returns these two bits of information as a Tuple<Type, IEnumerable<Type>>, where the first item is the common base type, if any, and the second item is the intersection of common interfaces
public class TypeTree
{
private TypeTree()
{
Children = new List();
}
public TypeTree(Type value)
: this()
{
// Get to the basest class
var typeChain = GetTypeChain(value).ToList();
Value = typeChain.First();
foreach (var type in typeChain.Skip(1))
{
Add(type);
}
}
public Type Value { get; private set; }
public TypeTree Parent { get; private set; }
public List Children { get; private set; }
public IEnumerable Interfaces
{
get
{
var myInterfaces = Children.Where(c => c.Value.IsInterface);
return Parent == null ? myInterfaces : myInterfaces.Concat(Parent.Interfaces).Distinct();
}
}
public TypeTree Find(Type type)
{
if (Value == type)
return this;
return Children.Select(child => child.Find(type)).FirstOrDefault(found => found != null);
}
public TypeTree Add(Type type)
{
TypeTree retVal = null;
if (type.IsInterface)
{
if (Value.GetInterfaces().Contains(type))
{
retVal = new TypeTree { Value = type, Parent = this };
Children.Add(retVal);
return retVal;
}
}
var typeChain = GetTypeChain(type);
var walkTypes =
from baseType in typeChain
let alreadyExists = Value == baseType || Children.Any(c => c.Value == baseType)
where !alreadyExists
select baseType;
foreach (var baseType in walkTypes)
{
if (baseType.BaseType == Value)
{
// Add this as a child of the current tree
retVal = new TypeTree { Value = baseType, Parent = this };
Children.Add(retVal);
}
if (Value.IsAssignableFrom(baseType))
{
// we can add this as a child, potentially
retVal = Children.Aggregate(retVal, (current, child) => child.Add(baseType) ?? current);
}
// add interfaces
var interfaces = baseType.GetInterfaces().Where(i => i != type);
foreach (var intType in interfaces)
{
(retVal ?? this).Add(intType);
}
}
return retVal;
}
public override string ToString()
{
var childTypeNames = Children.Select(c => c.ToString()).Distinct();
return string.Format("({0} {1})", Value.Name, string.Join(" ", childTypeNames));
}
public static Tuple> GetCommonBases(Type left, Type right)
{
var tree = new TypeTree(left);
tree.Add(right);
var findLeft = tree.Find(left);
var findRight = tree.Find(right);
var commonInterfaces =
findLeft.Interfaces.Select(i => i.Value)
.Intersect(findRight.Interfaces.Select(i => i.Value))
.Distinct();
var leftStack = new Stack();
var temp = findLeft;
while (temp != null)
{
leftStack.Push(temp);
temp = temp.Parent;
}
var rightStack = new Stack();
temp = findRight;
while (temp != null)
{
rightStack.Push(temp);
temp = temp.Parent;
}
var zippedPaths = leftStack.Zip(rightStack, Tuple.Create);
var result = zippedPaths.TakeWhile(tup => tup.Item1.Value == tup.Item2.Value).Last();
return Tuple.Create(result.Item1.Value, commonInterfaces);
}
private static IEnumerable GetTypeChain(Type fromType)
{
var typeChain = new Stack();
var temp = fromType;
while (temp != null)
{
typeChain.Push(temp);
temp = temp.BaseType;
}
return typeChain;
}
}
I'll have a default implementation and some well-known classes and interface sorted by priority to have in mind. Here my implementation:
private static List<Type> CommonTypesPriorities = new List<Type>
{
typeof(IEnumerable),
typeof(Array),
typeof(IClonable)
};
public static Type FindAssignableWith(this Type type1, Type type2)
{
if(type1 == type2)
return type1;
var baseClass = type1.FindBaseClassWith(type2);
//if the base class is not object/null and it is not in the list, then return it.
if(baseClass != typeof(object) && baseClass != null && !CommonTypesPriorities.Contains(type))
return baseClass;
var #interface = type1.FindInterfaceWith(type2);
if(#interface == null)
return baseClase;
//if there's no base class and the found interface is not in the list, return it
if(baseClass != null && !CommonTypesPriorities.Contains(#interface)
return #interface;
//Now we have some class and interfaces from the list.
Type type = null;
int currentPriority;
//if the base class is in the list, then use it as the first choice
if(baseClass != null && CommonTypesPriorities.Contains(type))
{
type = baseClass;
currentPriority = CommonTypesPriorities.IndexOf(type);
}
var interfaces1 = type1.GetInterfaces();
var interfaces2 = type2.GetInterfaces();
foreach(var i in interfaces1)
{
if(interfaces2.Contains(i))
{
//We found a common interface. Let's check if it has more priority than the current one
var priority = CommonTypesPriorities.IndexOf(i);
if(i >= 0 && i < currentPriority)
{
currentPriority = priority;
type = i;
}
}
}
return type;
}
Hope it helps.
update +1: And now, without the stupid mistake and some more details
I suppose this is what you are looking for:
public static Type FindAssignableWith(this Type typeLeft, Type typeRight) {
if(typeLeft==null||typeRight==null)
return null;
var typeLeftUion=typeLeft.GetInterfaceHierarchy().Union(typeLeft.GetClassHierarchy());
var typeRightUion=typeRight.GetInterfaceHierarchy().Union(typeRight.GetClassHierarchy());
return
typeLeftUion.Intersect(typeRightUion)
.OrderByDescending(interfaceInHierarhy => interfaceInHierarhy.GetInterfaces().Contains(typeof(IEnumerable)))
.ThenByDescending(interfaceInHierarhy => interfaceInHierarhy.Equals(typeof(IEnumerable)))
.FirstOrDefault();
}
Basically it treats the base classes and interfaces the same in the ordering.
I suppose the base implementation is from [here].
What I did is basically glue the two methods together, without changing the semantics of the original functionality.
Example:
var result=typeof(char[]).FindAssignableWith2(typeof(string[]));
Console.WriteLine("{0}", typeof(char[]).FindAssignableWith2(typeof(string[]))); // IList
Console.WriteLine("{0}", typeof(Test).FindAssignableWith2(typeof(string[]))); // Object
// and so on...

Generic class to create concrete class automatically

Is there a way to take an interface, say:
/// <summary>
/// Interface containing operators which operate on T
/// </summary>
public interface IScalarOperators<T>
{
// Adds two T objects
IOperateScalar<T> OperatorAdd { get; }
// Subtracts two T objects
IOperateScalar<T> OperatorSubtract { get; }
// Multiplies two T objects
IOperateScalar<T> OperatorMultiply { get; }
}
// Class containing all the Scalar operators for a given T
class ScalarOperators<T> : IScalarOperators<T>
{
public IOperateScalar<T> OperatorAdd { get; private set; }
public IOperateScalar<T> OperatorSubtract { get; private set; }
public IOperateScalar<T> OperatorMultiply { get; private set; }
private ScalarOperators(IOperateScalar<T> add, IOperateScalar<T> subtract, IOperateScalar<T> multiply)
{
this.OperatorAdd = add;
this.OperatorSubtract = subtract;
this.OperatorMultiply = multiply;
}
public static ScalarOperators<bool> CreateBool()
{
return new ScalarOperators<bool>(new AddBool(), new SubtractBool(), new MultiplyBool());
}
public static ScalarOperators<int> CreateInt()
{
return new ScalarOperators<int>(new AddInt(), new SubtractInt(), new MultiplyInt());
}
// METHOD I WANT TO ADD
public static ScalarOperators<T> Create()
{
// if T == bool
// return CreateBool()
// if T == int
// return CreateInt()
// else (no definition available for T)
// return null
}
// I tried something like below, but it didn't work...
public static ScalarOperators<T> Create<T>() where T: bool
{ return CreateBool(); }
public static ScalarOperators<T> Create<T>() where T : int
{ return CreateInt(); }
public static ScalarOperators<T> Create<T>()
{ return null; }
}
Notice, I'd like a generic Create method which creates the correct set of operators, but I'm not sure how to do it.
I'd like to use it to remove the parameter from this method:
public static IMatrix<T> Add<T>(this IMatrix<T> matrix, IMatrix<T> other, IScalarOperators<T> operators)
{
JoinCells<T> joiner = new JoinCells<T>();
return joiner.Join(matrix, other, null, operators.OperatorAdd);
}
becomes
public static IMatrix<T> Add<T>(this IMatrix<T> matrix, IMatrix<T> other)
{
JoinCells<T> joiner = new JoinCells<T>();
return joiner.Join(matrix, other, null, ScalarOperators<T>.Create().OperatorAdd);
}
Thanks for any help! Mainly, I just don't want to have to pass the scalarOperator object to the extension method, I'd prefer to have a 'default' since it is unlikely that the ScalarOperators will change for any T that is defined.
i suggest making a factory of IScalarOperators instead of static class ( if your really need it to be static you could access it by static field ).
you could register them at app startup and get them by this example metod:
public IScalarOperators<T> Create<T>()
{
// check if exists in dictionary
return (ScalarOperators<T>)dict[typeof(T)];
}
dict will be of type Dictionary.
The adventage is that you could add new IScalarOperators during application grow only by creating new implementing class and registering it in factory, casting is a drawback. Also you will have better seperation of concerns and ( in my opinion ) cleaner code.
What you need to do is get the type of T.
Your Create method could be like this:
public static ScalarOperators<T> Create()
{
Type type = typeof(T);
if(type == typeof(bool))
return CreateBool()
if(type == typeof(int))
return CreateInt()
else
return null
}
There are a few things happening here that I think should be addressed. You're trying to segregate your custom operators from the types that they operate on, which is confusing, and you're trying to take the very broad concept of generics and then specialize them.
For the first one, you're always going to use the same operators for the same type (at least, you're never going to try and use bool operators on an int type). There's no reason to complicate things by having a separate class for them. For the latter, generic classes and generic methods are meant to work the same for any given T. Granted, you very well could get the typeof(T) in your static factory method and compare against that for several specific cases, and then you'll have to change that for every new T that you want to handle because of this overly complicated generic operand structure.
I would recommend creating a generic interface for your operands and then implementing a wrapper for those types instead. For example, int can be wrapped like this.
public interface IScalarOperators<T>
{
IScalarOperators<T> Add (IScalarOperators<T> rightSide);
IScalarOperators<T> Subtract (IScalarOperators<T> rightSide);
IScalarOperators<T> Multiply (IScalarOperators<T> rightSide);
T Unwrap();
}
public interface IMatrix<T> where T : IScalarOperators<T> { /* whatever */ }
public class CustomInt : IScalarOperators<CustomInt>
{
private readonly int number;
public CustomInt(int number) { this.number = number; }
public CustomInt Unwrap() { return this; }
public IScalarOperators<CustomInt> Add(IScalarOperators<CustomInt> rightSide) { return new CustomInt(number + rightSide.Unwrap().number); }
public IScalarOperators<CustomInt> Subtract(IScalarOperators<CustomInt> rightSide) { return new CustomInt(number - rightSide.Unwrap().number); }
public IScalarOperators<CustomInt> Multiply(IScalarOperators<CustomInt> rightSide) { return new CustomInt(number * rightSide.Unwrap().number); }
}
At that point, you can operate on an IMatrix<CustomInt> through the IScalarOperators<T> interface and perform any exposed operations you want. As a rough example, assuming you have an exposed accessor called array, you could say IScalarOperators<T> result = matrix.array[0, 0].Add(matrix.array[0, 1]); and get a representation back of adding the two together. You could then perform any further operations on that, and so on.

Store generic data in a non-generic class

I have a DataGridView that I want to use to store generic data. I want to keep a typed data list in the DataGridView class so that all of the sorts, etc. can be handled internally. But I don't want to have to set the type on the DataGridView since I won't know the data type until the InitializeData method is called.
public class MyDataGridView : DataGridView {
private List<T> m_data;
public InitializeData<T>(List<T> data) {
m_data = data;
}
... internal events to know when the datagrid wants to sort ...
m_data.Sort<T>(...)
}
Is this possible? If so, how?
If you won't know the type until you call InitializeData, then the type clearly can't be a compile-time part of the object.
Do you know everything you need to know about the sorting when you call InitializeData<T>? If so, how about you do something like:
private IList m_data;
private Action m_sorter;
public InitializeData<T>(List<T> data)
{
m_data = data;
// This captures the data variable. You'll need to
// do something different if that's not good enough
m_sorter = () => data.Sort();
}
Then when you need to sort later, you can just call m_sorter().
If you might sort on different things, you could potentially change it from an Action to Action<string> or whatever you'd need to be able to sort on.
If Jon's answer isn't sufficient, here's a more general (but more involved, and probably somewhat more confusing) approach:
/// <summary>
/// Allows a list of any type to be used to get a result of type TResult
/// </summary>
/// <typeparam name="TResult">The result type after using the list</typeparam>
interface IListUser<TResult>
{
TResult Use<T>(List<T> list);
}
/// <summary>
/// Allows a list of any type to be used (with no return value)
/// </summary>
interface IListUser
{
void Use<T>(List<T> list);
}
/// <summary>
/// Here's a class that can sort lists of any type
/// </summary>
class GenericSorter : IListUser
{
#region IListUser Members
public void Use<T>(List<T> list)
{
// do generic sorting stuff here
}
#endregion
}
/// <summary>
/// Wraps a list of some unknown type. Allows list users (either with or without return values) to use the wrapped list.
/// </summary>
interface IExistsList
{
TResult Apply<TResult>(IListUser<TResult> user);
void Apply(IListUser user);
}
/// <summary>
/// Wraps a list of type T, hiding the type itself.
/// </summary>
/// <typeparam name="T">The type of element contained in the list</typeparam>
class ExistsList<T> : IExistsList
{
List<T> list;
public ExistsList(List<T> list)
{
this.list = list;
}
#region IExistsList Members
public TResult Apply<TResult>(IListUser<TResult> user)
{
return user.Use(list);
}
public void Apply(IListUser user)
{
user.Use(list);
}
#endregion
}
/// <summary>
/// Your logic goes here
/// </summary>
class MyDataGridView
{
private IExistsList list;
public void InitializeData<T>(List<T> list)
{
this.list = new ExistsList<T>(list);
}
public void Sort()
{
list.Apply(new GenericSorter());
}
}
You should define delgates or an interface for any generic operations you need to perform at runtime. As Jon Skeet mentioned, you can't strongly-type your data grid if you don't know the types at compile time.
This is the way the framework does it. For example:
Array.Sort();
Has a few ways it can be used:
Send it an array of objects that implement IComparable or IComparable<T>
Send in a second parameter, which is a class that implements IComparer or IComparer<T>. Used to compare the objects for sorting.
Send in a second parameter, which is a Comparison<T> delegate that can be used to compare objects in the array.
This is an example of how you approach the problem. At its most basic level, your scenario can be solved by a strategy pattern, which is what Array.Sort() does.
If you need to sort by things dynamically at run time, I would create an IComparer class that takes the column you want to sort by as an argument in its constructor. Then in your compare method, use that column as the sort type.
Here is an example of how you would do it using some basic example classes. Once you have these classes set up, then you'd pass both into your data grid and use them where appropriate.
public class Car
{
public string Make { get; set; }
public string Model { get; set; }
public string Year { get; set; }
}
public class CarComparer : IComparer
{
string sortColumn;
public CarComparer(string sortColumn)
{
this.sortColumn = sortColumn;
}
public int Compare(object x, object y)
{
Car carX = x as Car;
Car carY = y as Car;
if (carX == null && carY == null)
return 0;
if (carX != null && carY == null)
return 1;
if (carY != null && carX == null)
return -1;
switch (sortColumn)
{
case "Make":
return carX.Make.CompareTo(carY.Make);
case "Model":
return carX.Model.CompareTo(carY.Model);
case "Year":
default:
return carX.Year.CompareTo(carY.Year);
}
}
}

Can a C# class inherit attributes from its interface?

This would appear to imply "no". Which is unfortunate.
[AttributeUsage(AttributeTargets.Interface | AttributeTargets.Class,
AllowMultiple = true, Inherited = true)]
public class CustomDescriptionAttribute : Attribute
{
public string Description { get; private set; }
public CustomDescriptionAttribute(string description)
{
Description = description;
}
}
[CustomDescription("IProjectController")]
public interface IProjectController
{
void Create(string projectName);
}
internal class ProjectController : IProjectController
{
public void Create(string projectName)
{
}
}
[TestFixture]
public class CustomDescriptionAttributeTests
{
[Test]
public void ProjectController_ShouldHaveCustomDescriptionAttribute()
{
Type type = typeof(ProjectController);
object[] attributes = type.GetCustomAttributes(
typeof(CustomDescriptionAttribute),
true);
// NUnit.Framework.AssertionException: Expected: 1 But was: 0
Assert.AreEqual(1, attributes.Length);
}
}
Can a class inherit attributes from an interface? Or am I barking up the wrong tree here?
No. Whenever implementing an interface or overriding members in a derived class, you need to re-declare the attributes.
If you only care about ComponentModel (not direct reflection), there is a way ([AttributeProvider]) of suggesting attributes from an existing type (to avoid duplication), but it is only valid for property and indexer usage.
As an example:
using System;
using System.ComponentModel;
class Foo {
[AttributeProvider(typeof(IListSource))]
public object Bar { get; set; }
static void Main() {
var bar = TypeDescriptor.GetProperties(typeof(Foo))["Bar"];
foreach (Attribute attrib in bar.Attributes) {
Console.WriteLine(attrib);
}
}
}
outputs:
System.SerializableAttribute
System.ComponentModel.AttributeProviderAttribute
System.ComponentModel.EditorAttribute
System.Runtime.InteropServices.ComVisibleAttribute
System.Runtime.InteropServices.ClassInterfaceAttribute
System.ComponentModel.TypeConverterAttribute
System.ComponentModel.MergablePropertyAttribute
You can define a useful extension method ...
Type type = typeof(ProjectController);
var attributes = type.GetCustomAttributes<CustomDescriptionAttribute>( true );
Here is the extension method:
/// <summary>Searches and returns attributes. The inheritance chain is not used to find the attributes.</summary>
/// <typeparam name="T">The type of attribute to search for.</typeparam>
/// <param name="type">The type which is searched for the attributes.</param>
/// <returns>Returns all attributes.</returns>
public static T[] GetCustomAttributes<T>( this Type type ) where T : Attribute
{
return GetCustomAttributes( type, typeof( T ), false ).Select( arg => (T)arg ).ToArray();
}
/// <summary>Searches and returns attributes.</summary>
/// <typeparam name="T">The type of attribute to search for.</typeparam>
/// <param name="type">The type which is searched for the attributes.</param>
/// <param name="inherit">Specifies whether to search this member's inheritance chain to find the attributes. Interfaces will be searched, too.</param>
/// <returns>Returns all attributes.</returns>
public static T[] GetCustomAttributes<T>( this Type type, bool inherit ) where T : Attribute
{
return GetCustomAttributes( type, typeof( T ), inherit ).Select( arg => (T)arg ).ToArray();
}
/// <summary>Private helper for searching attributes.</summary>
/// <param name="type">The type which is searched for the attribute.</param>
/// <param name="attributeType">The type of attribute to search for.</param>
/// <param name="inherit">Specifies whether to search this member's inheritance chain to find the attribute. Interfaces will be searched, too.</param>
/// <returns>An array that contains all the custom attributes, or an array with zero elements if no attributes are defined.</returns>
private static object[] GetCustomAttributes( Type type, Type attributeType, bool inherit )
{
if( !inherit )
{
return type.GetCustomAttributes( attributeType, false );
}
var attributeCollection = new Collection<object>();
var baseType = type;
do
{
baseType.GetCustomAttributes( attributeType, true ).Apply( attributeCollection.Add );
baseType = baseType.BaseType;
}
while( baseType != null );
foreach( var interfaceType in type.GetInterfaces() )
{
GetCustomAttributes( interfaceType, attributeType, true ).Apply( attributeCollection.Add );
}
var attributeArray = new object[attributeCollection.Count];
attributeCollection.CopyTo( attributeArray, 0 );
return attributeArray;
}
/// <summary>Applies a function to every element of the list.</summary>
private static void Apply<T>( this IEnumerable<T> enumerable, Action<T> function )
{
foreach( var item in enumerable )
{
function.Invoke( item );
}
}
Update:
Here is a shorter version as proposed by SimonD in a comment:
private static IEnumerable<T> GetCustomAttributesIncludingBaseInterfaces<T>(this Type type)
{
var attributeType = typeof(T);
return type.GetCustomAttributes(attributeType, true)
.Union(type.GetInterfaces().SelectMany(interfaceType =>
interfaceType.GetCustomAttributes(attributeType, true)))
.Cast<T>();
}
An article by Brad Wilson about this: Interface Attributes != Class Attributes
To summarise: classes don't inherit from interfaces, they implement them. This means that the attributes are not automatically part of the implementation.
If you need to inherit attributes, use an abstract base class, rather than an interface.
While a C# class does not inherit attributes from its interfaces, there is a useful alternative when binding models in ASP.NET MVC3.
If you declare the view's model to be the interface rather than the concrete type, then the view and the model binder will apply the attributes (e.g., [Required] or [DisplayName("Foo")] from the interface when rendering and validating the model:
public interface IModel {
[Required]
[DisplayName("Foo Bar")]
string FooBar { get; set; }
}
public class Model : IModel {
public string FooBar { get; set; }
}
Then in the view:
#* Note use of interface type for the view model *#
#model IModel
#* This control will receive the attributes from the interface *#
#Html.EditorFor(m => m.FooBar)
This is more for people looking to extract attributes from properties that may exist on an implemented interface. Because those attributes are not part of the class, this will give you access to them. note, I have a simple container class that gives you access to the PropertyInfo - as that is what I needed it for. Hack up as you need. This worked well for me.
public static class CustomAttributeExtractorExtensions
{
/// <summary>
/// Extraction of property attributes as well as attributes on implemented interfaces.
/// This will walk up recursive to collect any interface attribute as well as their parent interfaces.
/// </summary>
/// <typeparam name="TAttributeType"></typeparam>
/// <param name="typeToReflect"></param>
/// <returns></returns>
public static List<PropertyAttributeContainer<TAttributeType>> GetPropertyAttributesFromType<TAttributeType>(this Type typeToReflect)
where TAttributeType : Attribute
{
var list = new List<PropertyAttributeContainer<TAttributeType>>();
// Loop over the direct property members
var properties = typeToReflect.GetProperties();
foreach (var propertyInfo in properties)
{
// Get the attributes as well as from the inherited classes (true)
var attributes = propertyInfo.GetCustomAttributes<TAttributeType>(true).ToList();
if (!attributes.Any()) continue;
list.AddRange(attributes.Select(attr => new PropertyAttributeContainer<TAttributeType>(attr, propertyInfo)));
}
// Look at the type interface declarations and extract from that type.
var interfaces = typeToReflect.GetInterfaces();
foreach (var #interface in interfaces)
{
list.AddRange(#interface.GetPropertyAttributesFromType<TAttributeType>());
}
return list;
}
/// <summary>
/// Simple container for the Property and Attribute used. Handy if you want refrence to the original property.
/// </summary>
/// <typeparam name="TAttributeType"></typeparam>
public class PropertyAttributeContainer<TAttributeType>
{
internal PropertyAttributeContainer(TAttributeType attribute, PropertyInfo property)
{
Property = property;
Attribute = attribute;
}
public PropertyInfo Property { get; private set; }
public TAttributeType Attribute { get; private set; }
}
}
One of the answers worked for attributes placed on the interface itself, but I was looking for interface property member attributes. I could not find it anywhere and had to alter some of the answers here to get what I needed. Going to leave the extension method I used here. This method will get all custom attributes of type T from a PropertyInfo including attributes placed on interfaces.
public static IEnumerable<T> GetAllCustomAttributes<T> (this MemberInfo member) where T: Attribute
{
return member.GetCustomAttributes<T>(true)
.Union(member.DeclaringType.GetInterfaces().SelectMany(i => i.GetProperties())
.Select(p => p.GetCustomAttribute<T>(true)));
}
For my case I have a lot of cards and each card can have a two icons, but those icons refer to different values. All the values were being defined on my interfaces and I didn't want to bring each down to the class implementation since it would be the same across all cards. My usage looks like:
public interface IConsumable
{
[CardIcon(CardIconPosition.Right)]
public int Food { get; }
}
public class FoodCard : IConsumable
{
public bool TryGetCardIcon(CardIconPosition cardIconPosition, out string text)
{
var property = Card.GetType().GetProperties()
.FirstOrDefault(p => p.GetAllCustomAttributes<CardIconAttribute>()?
.Any(c => c.CardIconPosition == cardIconPosition) ?? false);
bool hasProperty = property != null;
text = string.Empty;
if (hasProperty)
{
text = property?.GetValue(Card).ToString() ?? string.Empty;
}
return hasProperty;
}
}
EDIT: this covers inheriting attributes from interfaces on members (incl. properties). There are simple answers above for type definitions. I just posted this because I found it to be an irritating limitation and wanted to share a solution :)
Interfaces are multiple inheritance and behave as inheritance in the type system. There isn't a good reason for this kind of stuff. Reflection is a bit hokey. I've added comments to explain the nonsense.
(This is .NET 3.5 because this it just happens to be what the project I'm doing at the moment is using.)
// in later .NETs, you can cache reflection extensions using a static generic class and
// a ConcurrentDictionary. E.g.
//public static class Attributes<T> where T : Attribute
//{
// private static readonly ConcurrentDictionary<MemberInfo, IReadOnlyCollection<T>> _cache =
// new ConcurrentDictionary<MemberInfo, IReadOnlyCollection<T>>();
//
// public static IReadOnlyCollection<T> Get(MemberInfo member)
// {
// return _cache.GetOrAdd(member, GetImpl, Enumerable.Empty<T>().ToArray());
// }
// //GetImpl as per code below except that recursive steps re-enter via the cache
//}
public static List<T> GetAttributes<T>(this MemberInfo member) where T : Attribute
{
// determine whether to inherit based on the AttributeUsage
// you could add a bool parameter if you like but I think it defeats the purpose of the usage
var usage = typeof(T).GetCustomAttributes(typeof(AttributeUsageAttribute), true)
.Cast<AttributeUsageAttribute>()
.FirstOrDefault();
var inherit = usage != null && usage.Inherited;
return (
inherit
? GetAttributesRecurse<T>(member)
: member.GetCustomAttributes(typeof (T), false).Cast<T>()
)
.Distinct() // interfaces mean duplicates are a thing
// note: attribute equivalence needs to be overridden. The default is not great.
.ToList();
}
private static IEnumerable<T> GetAttributesRecurse<T>(MemberInfo member) where T : Attribute
{
// must use Attribute.GetCustomAttribute rather than MemberInfo.GetCustomAttribute as the latter
// won't retrieve inherited attributes from base *classes*
foreach (T attribute in Attribute.GetCustomAttributes(member, typeof (T), true))
yield return attribute;
// The most reliable target in the interface map is the property get method.
// If you have set-only properties, you'll need to handle that case. I generally just ignore that
// case because it doesn't make sense to me.
PropertyInfo property;
var target = (property = member as PropertyInfo) != null ? property.GetGetMethod() : member;
foreach (var #interface in member.DeclaringType.GetInterfaces())
{
// The interface map is two aligned arrays; TargetMethods and InterfaceMethods.
var map = member.DeclaringType.GetInterfaceMap(#interface);
var memberIndex = Array.IndexOf(map.TargetMethods, target); // see target above
if (memberIndex < 0) continue;
// To recurse, we still need to hit the property on the parent interface.
// Why don't we just use the get method from the start? Because GetCustomAttributes won't work.
var interfaceMethod = property != null
// name of property get method is get_<property name>
// so name of parent property is substring(4) of that - this is reliable IME
? #interface.GetProperty(map.InterfaceMethods[memberIndex].Name.Substring(4))
: (MemberInfo) map.InterfaceMethods[memberIndex];
// Continuation is the word to google if you don't understand this
foreach (var attribute in interfaceMethod.GetAttributes<T>())
yield return attribute;
}
}
Barebones NUnit test
[TestFixture]
public class GetAttributesTest
{
[AttributeUsage(AttributeTargets.All, AllowMultiple = true, Inherited = true)]
private sealed class A : Attribute
{
// default equality for Attributes is apparently semantic
public override bool Equals(object obj)
{
return ReferenceEquals(this, obj);
}
public override int GetHashCode()
{
return base.GetHashCode();
}
}
[AttributeUsage(AttributeTargets.All, AllowMultiple = true, Inherited = false)]
private sealed class ANotInherited : Attribute { }
public interface Top
{
[A, ANotInherited]
void M();
[A, ANotInherited]
int P { get; }
}
public interface Middle : Top { }
private abstract class Base
{
[A, ANotInherited]
public abstract void M();
[A, ANotInherited]
public abstract int P { get; }
}
private class Bottom : Base, Middle
{
[A, ANotInherited]
public override void M()
{
throw new NotImplementedException();
}
[A, ANotInherited]
public override int P { get { return 42; } }
}
[Test]
public void GetsAllInheritedAttributesOnMethods()
{
var attributes = typeof (Bottom).GetMethod("M").GetAttributes<A>();
attributes.Should()
.HaveCount(3, "there are 3 inherited copies in the class heirarchy and A is inherited");
}
[Test]
public void DoesntGetNonInheritedAttributesOnMethods()
{
var attributes = typeof (Bottom).GetMethod("M").GetAttributes<ANotInherited>();
attributes.Should()
.HaveCount(1, "it shouldn't get copies of the attribute from base classes for a non-inherited attribute");
}
[Test]
public void GetsAllInheritedAttributesOnProperties()
{
var attributes = typeof(Bottom).GetProperty("P").GetAttributes<A>();
attributes.Should()
.HaveCount(3, "there are 3 inherited copies in the class heirarchy and A is inherited");
}
[Test]
public void DoesntGetNonInheritedAttributesOnProperties()
{
var attributes = typeof(Bottom).GetProperty("P").GetAttributes<ANotInherited>();
attributes.Should()
.HaveCount(1, "it shouldn't get copies of the attribute from base classes for a non-inherited attribute");
}
}
Add interface with properties that have attributes/custom attributes attached to the same properties that class have. We can extract the interface of the class by using Visual studio refactor feature.
Have a partial class implement that interface.
Now Get "Type" object of the class object and get custom attributes from the property info using getProperties on Type object.
This will not give the custom attributes on the class object as the class properties did not had the interface properties' custom attributes attached/inherited.
Now call GetInterface(NameOfImplemetedInterfaceByclass) on the class's Type object retrieved above. This will
provide the interface's "Type" object. we should know the implemented interface's NAME. From Type object get property information and if the interface's property has any custom attributes attached then property information will provide
custom attribute list. The implementing class must have provided implementation of the interface's properties.
Match the class object's specific property name within the list of the interface's property information to get the custom attributes list.
This will work.
Though my answer is late and specific to a certain case, I would like to add some ideas.
As suggested in other answers, Reflection or other methods would do it.
In my case a property (timestamp) was needed in all models to meet certain requirement (concurrency check attribute) in a Entity framework core project.
We could either add [] above all class properties (adding in IModel interface which models implemented, didn't work). But I saved time through Fluent API which is helpful in these cases. In fluent API, I can check for specific property name in all models and set as IsConcurrencyToken() in 1 line !!
var props = from e in modelBuilder.Model.GetEntityTypes()
from p in e.GetProperties()
select p;
props.Where(p => p.PropertyInfo.Name == "ModifiedTime").ToList().ForEach(p => { p.IsConcurrencyToken = true; });
Likewise if you need any attribute to be added to same property name in 100's of classes/models, we can use fluent api methods for inbuilt or custom attribute resolver.
Though EF (both core and EF6) fluent api may use reflection behind the scenes, we can save effort :)

Categories

Resources