Mustafa Ozturk
Mustafa Ozturk

Reputation: 811

Is it possible to relate two types together?

This is a thought exercise. I don't need help simplifying this code or to accomplish the same thing without relating the types. The code is convoluted because it attempts to identify a pattern that could be used if alternatives were not available.

The idea is to see if one can create arbitrary relationships between various types that is enforced by the compiler.

I want to be able create a set of types {T1, T2, T3, T4, ...} that are related to another set of types {Ta, Tb, Tc, Td, ... } in the same way. Once the relationship is established, I want to be able to use a type in the second set, by only using the related type in the first set. For example, if a function is given type T5, it should be able to create an instance of Te because T5 and Te are related.

In the example below, I'm using the types {Nail, Screw} and I want to relate them to their makers {NailMaker, ScrewMaker}. One constraint of this thought exercise is to use the type Nail to create a NailMaker, and not an instance of Nail to do so.

The objective is to be able to call a static member of a base class Maker with a type in the first set, to make an instance of the related type in the second set:

var factory = Maker<Nail>.Get()

Here factory would be an instance of NailMaker derived from Maker<Nail>, and Get() is a static function.

I need to somehow relate NailMaker to Nail but I haven't found a way to do that.

Something like:

static public Maker<T> Get()
{
   return T.GetMaker();
}

I have tried this and it works:

public abstract class Maker<T>
{

    static public Maker<T> Get<T2>() where T2: Maker<T>, new()
    {
        return new T2();
    }
}

However, I'd like it to work without passing T2.

Upvotes: 1

Views: 158

Answers (2)

Franck
Franck

Reputation: 4440

Editing the whole answer as this is much cleaner and closer to what you need.

First the Maker class (your T2). You would add the generic properties and methods your need :

public class Maker 
{ 
    public string Name { get; set; } = ""; 
}

Then the Part parent class that describe the parts and contain the matching Maker class

public class Part<T> where T : Maker 
{ 
    public static Type MakerType { get { return typeof(T); } } 
}

Then you need 1 Maker to match each Part so you create those :

public class NailMaker : Maker { public NailMaker() { Name = "Nail"; } }

public class ScrewMaker : Maker { public ScrewMaker() { Name = "Screw"; } }

Then we need the Part for each and with the T2 / Maker class they are referring too.

public class Nail : Part<NailMaker> { }

public class Screw : Part<ScrewMaker> { }

Then getting the Maker class only required instantiation of the Type lying in the Part class that is Static hence no need to instantiate the Part class

var nailMaker = Activator.CreateInstance(Nail.MakerType);    
var screwMaker = Activator.CreateInstance(Screw.MakerType);    

Upvotes: 2

Marcos Jonatan Suriani
Marcos Jonatan Suriani

Reputation: 794

I'm not sure where you will apply the usage of it, but refering to Factory pattern you can implement something like this:

abstract class Maker {
   public abstract int SomeProperty { get; }
}

abstract class MakerFactory {
   public abstract Maker GetMaker();
}


class Nail:Maker {

}

class ConcreteNailFactory:NailFactory {
   public override Maker GetMaker() {
      return new Nail();
   }
}

Upvotes: 0

Related Questions