In my game I have merchants. All items have a standard price. Each merchant has an interpretation of this price. I have an item inheritance hierarchy. ConsumableItem and EquipableItem inherits from the base class GameItem, HoldableEquipableItem inherits from EquipableItem and so on. A merchant can add a multiplier to one of these types, so if he has a multiplier of 0.5 on EquipableItem it means EquipableItem and all types inheriting from it will have their price multiplied with 0.5 (halved).
The inheritance hierarchy fits my problem since it doesn't have to be retyped anywhere and the tool Type.IsSubclassOf is built in available.But I'm not too fond of using types for game mechanics mainly because I want to show the type in the Unity inspector and it doesn't support Type, so I would have to use a string to symbolize it and parse the type afterward (maybe also 'ethical' and performance issues?).
Is there a good way I could implement this with a string or enum type instead of Type? A class where you had a method similar to IsSubclassOf just using string/enum instead. The type of the item could either be reflected through a field/property, or just convert GetType in the hierarchy to the string/enum version.
I would go with something like this in your case:
public class GameItem {
public List<string> Type { get; private set; }
GameItem(List<string> type)
{
Type = type;
Type.Add(nameof(GameItem))
}
public IsType(string type)
{
return Type.Contains(type);
}
}
public class SubGameItem : GameItem
{
public SubGameItem(List<string> type)
: base(new List<string>(type){nameof(SubGameItem)})
{
}
}
If this is too hard coded for you, I will have to say I don't understand why, I think this is the least hardcoded way you can do to solve your issue, and it is probably better than using Type class.
If you don't have c#6, you will have to do it hardcoded, but I would use enums instead of string in that case (I would use enums anyway, but if you don't want have to make sure you updated the enum for each change, this is fine).
I forgot to post this. Here is my solution to the problem if anyone needs it.
/// <summary>
/// Mimics the Type inheritance hierarchy for enums
/// </summary>
// Enum is a special class that cannot be used as a constraint, so instead use its parent interface IConvertible
public class InheritanceHierarchy<T> where T : IConvertible
{
private Dictionary<T, InheritanceElement<T>> elements =
new Dictionary<T, InheritanceElement<T>>();
public void Add(T element, T parent)
{
var parentElement = parent.Equals(default(T)) ? null : elements[parent];
elements.Add(element, new InheritanceElement<T>(element, parentElement));
}
/// <summary>
/// Add parent for multiple children
/// </summary>
public void Add(T parent, params T[] elements)
{
foreach (var element in elements)
Add(element, parent);
}
public bool IsSameOrSubclass(T element, T parent)
{
return ParentIndex(element, parent) != -1;
}
/// <summary>
/// Get how many parents the element is from parent. If they don't relate return -1
/// </summary>
public int ParentIndex(T element, T parent)
{
// If the element is same as parent
if (element.Equals(parent))
return 0;
// Loop through the chain of parents checking until it is either null or a match
var actualParent = elements[element].parent;
var parentIndex = 1;
while (actualParent != null)
{
if (parent.Equals(actualParent.element))
return parentIndex;
else
{
actualParent = actualParent.parent;
parentIndex++;
}
}
return -1;
}
}
public class InheritanceElement<T> where T : IConvertible
{
public T element;
public InheritanceElement<T> parent;
public InheritanceElement(T element, InheritanceElement<T> parent)
{
this.element = element;
this.parent = parent;
}
}
Related
Im having design/ architecture issues in how I am putting together my code. For example right now I store data in:
internal interface IProperty<TKey1, TKey2> : IDictionary<TKey1, TKey2> { }
internal class PropertyDictionary<TKey1, TKey2> : IProperty<TKey1, TKey2>
I implement IDictionary in PropertyDictionary. Also with PropertyDictionary i can then have a key and then for the value an immutable object with public properties. I can then reference the data easily by:
foreach (var data in inputData.Values)
{
var propertyValue = data.MyDataProperty;
}
Firstly this way seems a lot of overhead to store data but more importantly now when I need to extend the functionality of PropertyDictionary for example to include RetrievePrice it becomes complicated as I need to add the additional methods in an interface and then create a new class as so:
internal interface IAssetPriceData<in TKey1>
{
double RetrievePrice(TKey1 key);
}
internal class PriceDictionary<TKey1, TKey2> : PropertyDictionary<TKey1, TKey2>, IAssetPriceData<TKey1>
So a solution on how I should structure my code to easily store different types of data which is then easily retrieved so I can manipulate / perform calculation on the properties that are being stored.
For anyone interested, I wrote a class somewhat like the one described here once (below). I was grouping properties of the same type for some WPF binding scenarios, and binding to dictionary elements. I didn't want to use a dictionary because of the key not found exception that would be raise (and eaten) by the framework. This one wraps a dictionary and hardcodes strings as keys, though it could probably be generalized to suit the purpose described here. The main item of note is the behavior of the indexer when key is not found -- it returns the default T instead of throwing exception.
/// This class represents a generic collection of things for binding
/// Hash items is never null, Indexer never throws exceptions, returning defaults on cache miss
public class BindableHash : IEnumerable
{
#region Fields
/// <summary>Current implementation of the hash is a dictionary</summary>
private readonly Dictionary<string, T> _HashItems = new Dictionary<string, T>();
#endregion
#region Properties
/// <summary>How many items are currently in the hash</summary>
public virtual int Count { get { return _HashItems.Count; } }
/// <summary>Indexer provides hashed (by string) lookup</summary>
public virtual T this[string index]
{
get { return index != null && _HashItems.ContainsKey(index) ? _HashItems[index] : default(T); }
}
#endregion
#region Constructors
/// <summary>Default constructor initializes hash with no members</summary>
public BindableHash() : this(null) { }
/// <summary>Injected constructor seeds the list using the tuples passsed in</summary>
public BindableHash(params Tuple<string, T>[] initialTuples)
{
foreach (Tuple<string, T> tuple in initialTuples ?? new Tuple<string, T>[] { })
{
Add(tuple);
}
}
#endregion
#region Methods
/// <summary>Add a key-value pair to the hash</summary>
public virtual void Add(string key, T value)
{
Add(new Tuple<string, T>(key, value));
}
/// <summary>Removes all items from the hash</summary>
public virtual void Clear()
{
_HashItems.Clear();
}
/// <summary>Remove a particular value from the hash</summary>
public bool Remove(string key)
{
return key != null && _HashItems.Remove(key);
}
#endregion
#region Helpers
/// <summary>Abstraction for adding a key value pair</summary>
protected void Add(Tuple<string, T> tuple)
{
if (tuple != null && tuple.Item1 != null)
{
_HashItems[tuple.Item1] = tuple.Item2;
}
}
#endregion
#region IEnumerable<T> Members
/// <summary>Define enumerator retrieval to allow enumeration over values</summary>
public IEnumerator<T> GetEnumerator()
{
foreach (T value in _HashItems.Values)
{
yield return value;
}
}
#endregion
#region IEnumerable Members
/// <summary>Impelementation for clients who cast this as non-generic IEnumerable</summary>
/// <remarks>If you're not familiar with the black magic going on here, IEnmerable generic interface inherits from
/// IEnumerable non-generic (legacy). Both interfaces define GetEnumerator, and one returns a generic IEnumerator and the other
/// a non-generic IEnumerator. This one is the non-generic, and we want to 'hide' it for type safety purposes. When you
/// do an explicit interface implementation, you create some kind of visibility purgatory. This method is not private/protected
/// because the interface is public, but it is also not a public method of this class. The only way you can get to this guy is by casting
/// BindableHash as IEnumerable (non-generic) and invoking the method that way. Since that is possible to do, we have to implement the method,
/// which we do by just invoking our generic one. This is legal because of the fact that IEnumerator generic inherits from non-generic IEnumerator.
/// Clear as mud? You can ask me for a more detailed explanation, if you like --ebd</remarks>
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
#endregion
}
Goal
I have a generic class GenericClass<T> and I want to pool instances.
I'm interested in seeing if I can get the syntax:
MyGenericPool = new GenericPool<GenericClass>();
// Or maybe it's MyGenericPool = new GenericPool<GenericClass<>>();
GenericClass<TGenericParam> GenericClassInstance =
MyGenericPool.Get<TGenericParam>();
(My understanding of generics says, no I can't, don't be silly the syntax doesn't exist / wouldn't work, but I'm intested in what others think).
Showing my workings
I'm a bit doubtful as from my understanding the types GenericClass<string> and GenericClass<int> aren't really related from the type system's point of view.
Now, I realise that I can get close, i.e.:
GenericClass<TGenericParam> GenericClassInstance =
GenericPool.Get<GenericClass<TGenericParam>>();
and then have the GenericPool just store a Dictionary<Type, ObjectPool<object>> somewhere.
I'm interested in seeing if I can avoid having to do that. I don't want to have to specify the generic type every time when, as the caller, i'm only changing the generic type parameter. I'd also like to be able to enforce (compile time) that all objects going into my GenericObjectPool<T> are of a set generic type (T<>).
I think the problem stems from not being able to treat a generic type parameter as being generic its self. If I could do that (can I already??) then maybe something like the below might work:
public class GenericClassPool<TGeneric> where TGeneric : class<>
{
private readonly Dictionary<Type, object> objectPools = new Dictionary<Type, object>();
private void EnsureObjectPoolExists<TGenericParam>()
{
if (!objectPools.ContainsKey(typeof(TGenericParam)))
{
objectPools.Add(typeof(TGenericParam), new ObjectPool<TGeneric<TGenericParam>>(() => Activator.CreateInstance(typeof(TGeneric<TGenericParam>)) as TGeneric<TGenericParam>));
}
}
private ObjectPool<TGeneric<TGenericParam>> GetPool<TGenericParam>()
{
EnsureObjectPoolExists<TGenericParam>();
return (objectPools[typeof(TGenericParam)] as ObjectPool<TGeneric<TGenericParam>>);
}
public void Add<TTypeParam>(TGeneric<TGenericParam> obj)
{
EnsureObjectPoolExists<TTypeParam>();
GetPool<TGenericParam>().Add(obj);
}
public TGeneric<TGenericParam> Get<TGenericParam>()
{
return GetPool<TGenericParam>().Get() as TGeneric<TGenericParam>;
}
}
Question
Can I get the syntax I want (at the top)? If not, how close can I get?
The solution / syntax you are trying to achieve doesn't work that way, because you can't use a generic type without its type parameters as the type parameter to another generic type.
However, you could achieve similar results with the following approach:
Create a base class for the class pool that requires you to supply the complete generic type
Create a derived class for the specific generic type
Something like that:
public class ObjectPool
{
Dictionary<Type, object> _objectPool = new Dictionary<Type, object>();
public void Add<TKey, TValue>(TValue value)
{
_objectPool.Add(typeof(TKey), value);
}
public TValue Get<TKey, TValue>() where TValue : class
{
object value;
if(_objectPool.TryGetValue(typeof(TKey), out value))
return value as TValue;
return null;
}
}
public class GenericClassPool : ObjectPool
{
public void Add<TGenericParam>(GenericClass<TGenericParam> obj)
{
Add<TGenericParam, GenericClass<TGenericParam>>(obj);
}
public GenericClass<TGenericParam> Get<TGenericParam>()
{
return Get<TGenericParam, GenericClass<TGenericParam>>();
}
}
Usage would then be like this:
var pool = new GenericClassPool();
pool.Add(new GenericClass<string> { Property = "String" });
pool.Add(new GenericClass<int> { Property = 0 });
GenericClass<string> firstObject = pool.Get<string>();
GenericClass<int> secondObject = pool.Get<int>();
The draw back of this solution is that you would need to create one pool class for each generic type you want to pool, so you potentially will have a lot of <className>Pool classes deriving from ObjectPool.
To make this usable, all real code needs to be in the ObjectPool class and only code that supplies the generic parameters remains in the derived classes.
I'd like to share my own pool classes. They have a similar API to the other code posted but are a bit more developed and flexible, in my totally biased opinion.
Single type object pool:
/// <summary>
/// Allows code to operate on a Pool<T> without casting to an explicit generic type.
/// </summary>
public interface IPool
{
Type ItemType { get; }
void Return(object item);
}
/// <summary>
/// A pool of items of the same type.
///
/// Items are taken and then later returned to the pool (generally for reference types) to avoid allocations and
/// the resulting garbage generation.
///
/// Any pool must have a way to 'reset' returned items to a canonical state.
/// This class delegates that work to the allocator (literally, with a delegate) who probably knows more about the type being pooled.
/// </summary>
public class Pool<T> : IPool
{
public delegate T Create();
public readonly Create HandleCreate;
public delegate void Reset(ref T item);
public readonly Reset HandleReset;
private readonly List<T> _in;
#if !SHIPPING
private readonly List<T> _out;
#endif
public Type ItemType
{
get
{
return typeof (T);
}
}
public Pool(int initialCapacity, Create createMethod, Reset resetMethod)
{
HandleCreate = createMethod;
HandleReset = resetMethod;
_in = new List<T>(initialCapacity);
for (var i = 0; i < initialCapacity; i++)
{
_in.Add(HandleCreate());
}
#if !SHIPPING
_out = new List<T>();
#endif
}
public T Get()
{
if (_in.Count == 0)
{
_in.Add(HandleCreate());
}
var item = _in.PopLast();
#if !SHIPPING
_out.Add(item);
#endif
return item;
}
public void Return( T item )
{
HandleReset(ref item);
#if !SHIPPING
Debug.Assert(!_in.Contains(item), "Returning an Item we already have.");
Debug.Assert(_out.Contains(item), "Returning an Item we never gave out.");
_out.Remove(item);
#endif
_in.Add(item);
}
public void Return( object item )
{
Return((T) item);
}
#if !SHIPPING
public void Validate()
{
Debug.Assert(_out.Count == 0, "An Item was not returned.");
}
#endif
}
Next, a multi-type pool.
There is no difference between using this class or using multiple Pool<T> yourself. But in some situations using this class will make code look cleaner, ie. eliminating if/else (type == foo) blocks.
/// <summary>
/// Represents a collection of pools for one or more object types.
/// </summary>
public class Pooler
{
private readonly List<IPool> _pools;
public Pooler()
{
_pools = new List<IPool>();
}
public void DefineType<T>(int initialCapacity, Pool<T>.Create createHandler, Pool<T>.Reset resetHandler)
{
var p = new Pool<T>(initialCapacity, createHandler, resetHandler);
_pools.Add(p);
}
public T Get<T>()
{
var p = GetPool(typeof (T));
if (p == null)
throw new Exception(string.Format("Pooler.Get<{0}>() failed; there is no pool for that type.", typeof(T)));
return ((Pool<T>)p).Get();
}
public void Return(object item)
{
var p = GetPool(item.GetType());
if (p == null)
throw new Exception(string.Format("Pooler.Get<{0}>() failed; there is no pool for that type.", item.GetType()));
p.Return(item);
}
private IPool GetPool(Type itemType)
{
foreach (var p in _pools)
{
if (p.ItemType == itemType)
{
return p;
}
}
return null;
}
}
As far as 'not having to specify the type parameter every time you access the pool', I often declare a concrete pool for a specific type that is frequently used.
public class GameObjectPool : Pool<GameObject>
{
public GameObjectPool(int initialCapacity)
:base(initialCapacity, CreateObject, ResetObject)
{
}
private GameObject CreateObject()
{ ... }
private GameObject ResetObject()
{ ... }
}
Then your code which was...
_pool = new Pool<GameObject>(10);
var obj = _pool.Get<GameObject>();
Can become...
_pool = new GameObjectPool(10);
var obj = _pool.Get();
Another option is...
using GameObjectPool=MyRootnamespace.Pool<GameObject>
Which can work if you have a ton of references to the pool, but they are all in the same code file.
I have class called GroupItem, i can store any type here say int, string, decimal, datetime etc.., Then, i have GroupItems which will store any groupItem. I'm using an arraylist to store all the groupItem.
public class GroupItem<T>
{
private string heading;
private List<T> items = new List<T>();
public GroupItem() { }
public string Heading
{
get { return heading; }
set { heading = value; }
}
public List<T> Items
{
get { return items; }
set { items = value; }
}
public void Add(T value)
{
this.items.Add(value);
}
public T this[int index]
{
get
{
return this.items[index];
}
}
}
public class GroupItems
{
private string groupName;
private List<object> items = new List<object>();
public string GroupName
{
get { return groupName; }
set { groupName = value; }
}
public GroupItems() { }
public void Add(object value)
{
this.items.Add(value);
}
public object this[int index]
{
get
{
return this.items[index];
}
}
}
I want to retrieve from GroupItems. How i can get generic item's values in groupItems?
I'm now inserting two items, datetime and int to groupitems. Now i want to retrieve groupitems[2] value but how i can convert this to groupItem without knowing what it is. Even we may get its genericarguments by getType().getGenericarguments()[0]. But how i can create an instance based upon that.
If the list is storing heterogeneous items, then I would suggest you need a common non-generic interface or base-class. So, say we have
interface IGroupItem {
// the non-generic members, and maybe
// "object Value {get;}" etc, and maybe
// "Type ItemTypr {get;}"
}
You would then have:
class GroupItem<T> : IGroupItem {...}
an you would then use
List<IGroupItem> ...
instead of ArrayList, or, franky, in place of GroupItems {...}
What I'd do is create a generic collection such as:
public class GroupItems<T> : List<GroupItem<T>>
{
}
If you need to extend the basic functionality of a list, you could also extend Collection<T> and override the methods you need:
public class GroupItems<T> : Collection<GroupItem<T>>
{
protected override void InsertItem(int index, T item)
{
// your custom code here
// ...
// and the actual insertion
base.InsertItem(index, item);
}
}
How about just replacing your GroupItems class with List<GroupItem<T>> ?
Depending on what you do with GroupItem you should either inherit from List/Collection as was offered by other or use a generic collection inside your class
e.g.
class GroupItem<T>
{
private List<T> items = new List<T>();
public void Add(T value)
{
items.Add(value);
}
public T Get()
{
//replace with some logic to detemine what to get
return items.First();
}
}
There are two situations that could be covered by your question:
You want to simply store a collection of GroupItem's of type T in the class GroupItems.
You want to store a collection of generic GroupItem's of any type in the class GroupItems. To better clarify, I mean that you could store GroupItem<DateTime> or GroupItem<int> in the same GroupItems class.
Here are some ways of going about storing and retrieving for both scenarios:
Same Type
public class GroupItem<T>
{
// ... Code for GroupItem<T>
}
public class GroupItems<T>
{
private List<GroupItem<T>> mItems = new List<GroupItem<T>>();
public void Add(T item)
{
mItems.Add(item);
}
public T GetItem(int index)
{
return mItems[index];
}
}
Here you will build a collections that contain GroupItem's of the same time, so a collection of GroupItem<DateTime> for example. All the items will be of the same type.
Generic Type
public interface IGroupItem
{
// ... Common GroupItem properties and methods
}
public class GroupItem<T>
{
// ... Code for GroupItem<T>
}
public class GroupItems
{
private List<IGroupItem> mItems = new List<IGroupItem>();
public void Add(IGroupItem item)
{
mItems.Add(item);
}
// This is a generic method to retrieve just any group item.
public IGroupItem GetItem(int index)
{
return mItems[index];
}
// This is a method that will get a group item at the specified index
// and then cast it to the specific group item type container.
public GroupItem<T> GetItem<T>(int index)
{
return (GroupItem<T>)mItems[index];
}
}
Here you will be able to build and maintain a single collection that can contain any GroupItem with any Type. So you could have a GroupItems collection that contains items of GroupItem<DateTime>, GroupItem<int>, etc.
Please note that none of these code examples take into account any erroneous circumstances.
Consider: you have a collection of items; the items may have any runtime type (string, int, etc.). Because of this, the static type of the collections items must be object.
It seems that you want to be able to retrieve items from the list with strong static typing. That's not possible without a lot of conditional logic (or reflection). For example:
object item = collection[0];
if (item is int)
//do something with an int
else if (item is string)
//do something with a string
Now suppose instead of "doing something" with the value of collection[0], we assign the value to a variable. We can do one of two things:
use the same variable for both cases, in which case the static type must be object.
use separate variables, in which case the static type will be string or int, but outside of the conditional logic, we can't know which variable holds the value of collection[0].
Neither option really solves the problem.
By creating GroupItem<T>, you add a level of indirection to this problem, but the underlying problem is still there. As an exercise, try reworking the example, but starting from "Consider: you have a collection of items; the items are of type GroupItem<T> where T may be any runtime type (string, int, etc.)."
Thanks for your inputs.
I have resolved it myself using multiple overloading methods to resolve this.
for example:
private void Print(GroupItem<string> items)
{
///custom coding
}
private void Print(GroupItem<int> items)
{
///custom coding
}
Though its not efficient enough, i want to do in this way as it was .net 2.0.
I'm now improving this in .Net 4.0 with new algorithm.
Thanks a lot for all of your helps.
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);
}
}
}
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 :)