Dariusz Woźniak Dariusz Woźniak - 2 months ago 11
C# Question

Property of generic type in non-generic class

Intro

I'm working with the legacy code which contains two classes:


  • I have a class which stores its value of
    System.Object
    type.
    (I named this class as
    DomainItem
    )

    • Its Identifier property refers to
      enum which holds information what a type of
      DomainItem
      is (in the
      context of business domain).


  • There is also a class which stores these
    items as an Enumerable List. (
    DomainItems
    )



What's more:


  • I don't want to change these classes into generic. This code is very sensitive and not covered by tests.

  • In order to get
    DomainItem
    , I must get it from
    DomainItems.Items
    collection.



Code

The code for classes is equivalent as below:

public class DomainItem
{
public Identifier Identifier { get; set; } // Readonly in the "real" code
public object Value { get; set; }
}

public class DomainItems
{
public IEnumerable<DomainItem> Items { get; set; }
}


The question is

How can I extend these classes using generics, to resolve type of Value property in the compile time. Is it even possible?

Example case might be as following:

DomainItem price = new DomainItem { Value = 25.20d, Identifier = Identifier.Price };
// ....
double priceValue = price.ProperValue; // generic property of type T


Obviously, above code is conceptual and it shows what I want to achieve. Any suggestions how to resolve that? Is it even possible?

Edit

My idea is to create a new
IEnumerable<DomainItem<T>>
where the collection is populated from non-generic
DomainItem
objects. Since the type of
DomainItem.Value
is known, it should be possible to make such collection somehow.

Answer

There's no such thing as a generic property, but you could easily create a generic method:

public T GetValue<T>() { ... }

public void SetValue<T>(T value) { ... }

You could then check typeof(T) within the method to make sure that it was appropriate for your identifier, ideally having made the identifier read-only. (It would be better as a constructor argument - I wouldn't expect it to make any sense to have a domain item whose identifier changed over time.)

Alternatively, you could just make the type of the Value property dynamic instead of object, assuming you're using C# 4+ with .NET 4+. Then your example code would compile - but it would perform an implicit (dynamic) conversion to double at execution time. You wouldn't get much safety there, but it would compile...