I have 3 objects that are very similar with only a few differences
public class Person
{
public Person(ResourceObject resource)
{
// resource comes from an API provided by one
// of our systems (i have no control over it)
this.ResourceObject = resource;
}
// Resource
internal ResourceObject ResourceObject { get; }
// Similar properties
public string ObjectID { get; }
public string ObjectType { get; }
public IEnumerable<string> PropertyNames { get; }
// Person-specific property example - Organisation
public string Organisation { get; set; }
}
public class Computer
{
public Computer(ResourceObject resource)
{
// resource comes from an API provided by one
// of our systems (i have no control over it)
this.ResourceObject = resource;
}
// Resource
internal ResourceObject ResourceObject { get; }
// Similar properties
public string ObjectID { get; }
public string ObjectType { get; }
public IEnumerable<string> PropertyNames { get; }
// Computer-specific property example - OperatingSystem
public string OperatingSystem { get; set; }
}
public class Group
{
public Group(ResourceObject resource)
{
// resource comes from an API provided by one
// of our systems (i have no control over it)
this.ResourceObject = resource;
}
// Resource
internal ResourceObject ResourceObject { get; }
// Similar properties
public string ObjectID { get; }
public string ObjectType { get; }
public IEnumerable<string> PropertyNames { get; }
// Group-specific property example - Members
public string Members { get; set; }
}
I currently have GetPerson, GetComputer and GetGroup methods that are working but they essentially do the same thing and then call one of the specific object constructors. In an effort to dive into the world of Generics and Interfaces and learn more (as you do) i attempted to create a GetResource<T> method that would do the same job as those 3 methods without all the duplicate code.
I created the IResource Interface to identify common properties:
public interface IResource
{
string ObjectID { get; }
string ObjectType { get; }
IEnumerable<string> PropertyNames { get; }
}
and then attempted to create a GetResource<T> method but got stuck at the return code:
public static T GetResource<T>(string identity) where T : IResource
{
// get resource from system API
// and then return T somehow?
return new T(resourceObject);
}
I thought of changing the return value from T to IResource but i'm still not sure how i would identify which class to return (Perhaps i need a base class? Resource perhaps).
The reason i turned to Generics for this specific situation is if the system API updates and suddenly has a new Location object i don't want to have to create a GetLocation method and then have 4 methods that do exactly the same thing except for one line of code.
Is this the correct use case for Generics? and if so how can my method figure out what object to return?
Use a base class to hold common behavior.
public abstract class Resource {
protected Resource (ResourceObject resource) {
// resource comes from an API provided by one
// of our systems (i have no control over it)
this.ResourceObject = resource;
}
// Resource
internal ResourceObject ResourceObject { get; }
// Similar properties
public string ObjectID { get; }
public string ObjectType { get; }
public IEnumerable<string> PropertyNames { get; }
}
Derived classes
public class Person : Resource {
public Person(ResourceObject resource):base(resource){
}
// Person-specific property example - Organisation
public string Organisation { get; set; }
}
public class Computer : Resource {
public Computer(ResourceObject resource) : base(resource) {
}
// Computer-specific property example - OperatingSystem
public string OperatingSystem { get; set; }
}
public class Group : Resource {
public Group(ResourceObject resource) : base(resource) {
}
// Group-specific property example - Members
public string Members { get; set; }
}
Interfaces can't be initialized and thus trying to pass a constructor argument wont work.
With the base class constraint the generic method becomes
public static T GetResource<T>(string identity) where T : Resource {
// get resource from system API
// and then return T somehow?
return (T) Activator.CreateInstance(typeof(T), resourceObject);
}
And used
Person person = GetResource<Person>("person_identity");
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With