Is it possible to do the following (If so I can\'t seem to get it working.. forgoing constraints for the moment)...
If the type (because it\'s ommitted) is inferred,
Actually it is possible if you know for sure that the generic T has the exact property, using the where (generic type constraint) for a specified class with where T : MyClass
.
For instance, if you have two entities Foo
and Boo
:
class Foo
{
public Guid Id {get; set;}
public DateTime CreateDate {get; set;}
public int FooProp {get; set;}
}
class Boo
{
public Guid Id {get; set;}
public DateTime CreateDate {get; set;}
public int BooProp {get; set;}
}
With a little refactor we can create a BaseClass
that will hold the common properties:
class BaseModel
{
public Guid Id {get; set;}
public DateTime CreateDate {get; set;}
}
And modify Foo
and Boo
to be:
class Boo : BaseModel
{
public int BooProp {get; set;}
}
class Foo : BaseModel
{
public int FooProp {get; set;}
}
And If you have a generic service with the constraint type of where T : BaseModel
the compiler will allow you to get or set the BaseModel
's properties.
Lets say that you want that for every entity (Foo
or Boo
) added to DB you will want to set the CreateDate
and Id
properties from code (and not from server default value):
public interface IGenericService<T>
{
void Insert(T obj);
}
public class GenericService<T> : IGenericService<T> where T : BaseModel
{
public void Insert(T obj)
{
obj.Id = Guid.NewGuid();
obj.CreateDate = DateTime.UtcNow;
this._repository.Insert(obj);
}
}
If you can't get make an interface for your type (or a common one between several types):
private void GetGenericTableContant<T>(ref StringBuilder outputTableContent, T item, Func<T, string> lineNumberAccessor)
{
outputTableContent.Append("<td>" + lineNumberAccessor(item) + "</td>");
}
Usage:
GetGenericTableContent(ref outputTableContent, item, x => x.SpreadsheetLineNumbers);
(Or you could just pass the SpreadSheetLineNumbers property if you don't really need the item reference in your method: void GetGenericTableContant<T>(ref StringBuilder outputTableContent, string lineNumbers)
)
No, it's not possible. Generic types must be known at compile time.
Think about it for a minute, how could compiler know that it is guaranteed that the type T
has SpreadsheetLineNumbers
property? What if T
is primitive type such as int
or object
?
What prevents us from calling method with ref _, 999
parameters (T is int here) ?
It'd only work if we add an interface that contains this property :
public interface MyInterface
{
string SpreadsheetLineNumbers { get; set; }
}
And let your class inherit from this interface
public class MyClass : MyInterface
{
public string SpreadsheetLineNumbers { get; set; }
}
Then we could use generic type constraints to let compiler know that the type T derives from this interface and therefore it has to contain and implement all its members:
private void GetGenericTableContent<T>(ref StringBuilder outputTableContent, T item)
where T : IMyInterface // now compiler knows that T type has implemented all members of the interface
{
outputTableContent.Append("<td>" + item.SpreadsheetLineNumbers + "</td>");
}