-1

I have five classes

class Program
{
    static void Main(string[] args)
    {
        Abstract test = new Child();
        test.Exectue();
    }
}


public abstract class Abstract
{
    public void Exectue()
    {
        IStrategy strategy = new Strategy();
        strategy.GetChildClassName();
    }
}


public class Child : Abstract
{
}


public interface IStrategy
{
    void GetChildClassName();
}


public class Strategy : IStrategy
{
    public void GetChildClassName()
    {
        ???
        Console.WriteLine();
    }
}

My question is, how can I get the name of a Child class (the one that is the instance of test variable) from Strategy class.

Doing this.GetType().Name yields "Strategy", and

var mth = new StackTrace().GetFrame(1).GetMethod();
var cls = mth.ReflectedType.Name; 

yields "Abstract" which is not what i want.

Is there any way that I can get the name of a Child class without doing some weird haxs, like throwing exception or passing type.

Kacper S.
  • 51
  • 1
  • 6
  • 1
    Do you count your attempt using `StackTrace` as a weird hack? – Sweeper Jun 16 '19 at 10:04
  • `StackTrace` approach also returns "Abstract". And no, beacause I know that there won't be any middle man between abstract and strategy – Kacper S. Jun 16 '19 at 10:06
  • Do you must use `Strategy` class to get the type or you can go with polymorphism ? – Stefan Jovanchevski Jun 16 '19 at 10:17
  • Yes I have to use Strategy class. In my real world scenario strategy class is responsible for validation and in this validation class I throw exception that contains the name of the Child class that isn't valid. – Kacper S. Jun 16 '19 at 10:20
  • You have *zero examples of nested classes*. – Erik Philips Jun 16 '19 at 10:24
  • Is it possible to pass the type of the child to the method of `Strategy` class? – Stefan Jovanchevski Jun 16 '19 at 10:32
  • It is but i would rather avoid this approach because it isn't really clean. Sure doing `strategy.GetChildClassName(this.GetType().Name);` solves the problem but my validator already takes two arguments and I was wondering if there is a more professional way of doing it – Kacper S. Jun 16 '19 at 10:37
  • The example and your explanation of the problem are not so good, and I don't think that someone can give you a more "professional" way for doing this. For example what kind of validations do you have? Where are you making those validations? You should describe the problem and provide additional information. – Stefan Jovanchevski Jun 16 '19 at 11:13
  • It doesn't matter what are my validations, its not my concern. My problem is how do i get the name of class that is "in charge" of starting the whole flow of this code. I deliberately didn't include the validation part in my post because it doesn't matter. The template for validation is exactly the same as I provided in the example – Kacper S. Jun 16 '19 at 11:33
  • @Stefcho Besides I don't see the reason why someone needs to see the details of my code to understand the main concept. I need strategy pattern for validation because the only difference in my Abstract class is the validation mechanism, which is based on some property (it doesn't matter which). The main concepts is, sometimes i need to validate things one way, other times another way. In both of these cases i need to throw exception with the name of the class that didn't pass the validation. Passing name of the class to the validation function only to make exception message is a code smell. – Kacper S. Jun 16 '19 at 11:36
  • @Kacper S. We don't need the details of your code but the interaction between the validation class and what it's validating is pretty crucial. There is no other interaction between the validator and the instances being validated? – MikeJ Jun 16 '19 at 12:48
  • The only interaction (and the reason why I need the name of the class) is that I am working with CRM and I need to validate plugin execution context. Plugin execution context has some properties that I need to validate. These properties are set up in "Child" classes. The only way I can know that given plugin takes properties from particular class is by the instance of `Abstract` class. I know kinda hectic but that's CRM for yall. I need the name of that class because I want to tell the programmer that his set up of the plugin is wrong – Kacper S. Jun 16 '19 at 13:02

2 Answers2

1

I don't know if this will satisfy your needs but you can send the current instance of the Abstract class to the Strategy class constructor and then get the current name of real type.

Or if you want to send only the name of the class instead of the whole instance you can do that also.

Update to the code

public abstract class Abstract
{
    public void Execute()
    {
        IValidator validator = new CustomClassValidator(this.GetType().Name);
        validator.Validate();
    }
}

public interface IValidator
{
    void Validate();
}


public class CustomClassValidator : IValidator
{
    private string className;

    public CustomClassValidator(string className)
    {
        this.className = className;
    }

    public void Validate()
    {
        // make some other validations and throw exceptions
        Console.WriteLine(className);
    }
}
  • I really want to avoid passing the whole instance of a class to the validate method (or anything that doesn't deal with validation for that matter), it breaks the separation of concerns because my validation depends on passing the instance of caller class, kinda overkill when I only need the name. And yes of course I can just pass the name, but getting the name for the validation purposes shouldn't be responsibility of a Abstract class, validation should be able to get that name itself – Kacper S. Jun 16 '19 at 12:11
  • Well, the responsibility of the `Validator` should be to validate the type of the class. Someone else should be responsible for sending the type to the `Validator` and in this case it is the `Abstract` class. With this approach we are protecting the code from future changes and we can use the `Validator` somewhere else. I made some changes to the code. – Stefan Jovanchevski Jun 16 '19 at 12:28
  • I am trying to avoid details because I have to deal with Dynamics CRM which will complicate things even more but. My `Validator` doesn't validate the type of the class. I only need the type of the class to create appropriate exception message. So that other programmer will know that he f up and he has to go the that particular class and make some changes. In our code base all classes with business logic inherit from `Abstract`. The truth is that `Validator` won't be used anywhere else because all 'important' classes are already using it implicitly via `Abstract`. – Kacper S. Jun 16 '19 at 12:36
  • I would totally agree with your solution if I would be doing some validations that require the name of the class, or instance. But in my case I only need it for exception message. I was hoping that we could read that information from reflection – Kacper S. Jun 16 '19 at 12:40
  • Do you throw the exception in your `Validator` class? I think in that case you can throw specific message for the error or validation that does not passed and catch it in the `Execute` method of the `Abstract` class where you can throw another exception with the message from the exception that was thrown and add additional info with the current class name. Or if you don't have specific error messages but only one generic in your `Validator` than you can return like bool value and check in the `Execute` method if the validations are good, if they are not than throw the exception from there. – Stefan Jovanchevski Jun 16 '19 at 12:53
  • That's one way to take down this problem but I think that your exaple of passing the name of class the validator is more readable. Still not ideal solution because I was really hoping that I can make use of reflection to avoid additional dependencies – Kacper S. Jun 16 '19 at 13:05
  • 1
    I think that using reflection will make you problems in the future because you are making the `Validator` to be aware of the `Abstract` class. And with the other approaches the `Validator` is doing only the work that he need to do. He does not need to know how to get the name of the class where he is encapsulated. His work is only to validate some things and to throw specific messages or to return result if everything is like it should be. – Stefan Jovanchevski Jun 16 '19 at 13:15
  • Good arguments I think i am gonna go with your solution. Thanks for the patients and for clearing things up – Kacper S. Jun 16 '19 at 13:19
0
public interface IStrategy
{
    string GetChildClassName();
}

public class Strategy : IStrategy
{
    public string GetChildClassName()
    {
        return this.GetType().Name;
    }
}
bzmind
  • 386
  • 3
  • 19
  • As i said before, this approach returns "Strategy". The name of the Child class should be encapsulated within the Strategy class as i only need to use it there. Separation of concerns – Kacper S. Jun 16 '19 at 11:43