Get the name of the class where the object was created - c#

I have two classes as follow:
First one:
class Class1
{
private void Method1()
{
var obj=new TestClass();
obj.TestMethod1();
}
}
Second One:
class TestClass
{
public void TestMethod1()
{
TestMethod2();
}
private void TestMethod2()
{
//get the calling class
}
}
When Class1.Method1 calls TestClass.TestMethod1 which in turn calls TestClass.TestMethod2, I want to get the fully qualified class name of Class1 inside TestClass.TestMethod2. I have seen this link, but I think I will get TestClass.TestMethod1 as method name and TestClass as the class name. How can I get the calling class name?

There is no nice way to do that. You can access the stack-frames (just look at the second frame, rather than the first) - but that is expensive and brittle. You could use optional caller-member-name attributes (being explicit from TestMethod1) to get hold of "Method1", but not the "Class1" part. One other option would be to pass in an object (or just the name) explicitly; for example:
private void Method1()
{
var obj=new TestClass();
obj.TestMethod1(this);
}
public void TestMethod1(object caller=null,
[CallerMemberName] string callerName=null)
{
TestMethod2(caller??this,callerName??"TestMethod1");
}
private void TestMethod2(object caller=null,
[CallerMemberName] string callerName=null)
{
string callerName = ((caller??this).GetType().Name) + "." + callerName
//get the calling class
}
but I have to confess that is pretty ugly
Perhaps better would be to question why you need this in the first place.

Could you not pass the type into the second class via constructor like:
class Class1
{
private void Method1()
{
Type t = typeof(Class1);
var obj = new TestClass(t);
obj.TestMethod1();
}
}
class TestClass
{
private Type _caller;
public TestClass(Type type)
{
_caller = type;
}
public void TestMethod1()
{
TestMethod2();
}
private void TestMethod2()
{
//Do something with the class
}
}

You might check out this code to find your solution without having to pass class instances or type parameters, etc....:
class Program
{
static void Main(string[] args)
{
var c = new Class1();
c.Method1();
}
}
class Class1
{
public void Method1()
{
var obj = new TestClass();
obj.TestMethod1();
}
}
class TestClass
{
public void TestMethod1()
{
TestMethod2();
var mth = new StackTrace().GetFrame(1).GetMethod();
var clss = mth.ReflectedType.Name;
Console.WriteLine("Classname in Method1(): {0}", clss);
}
private void TestMethod2()
{
//get the calling class
var mth = new StackTrace().GetFrame(1).GetMethod();
var clss = mth.ReflectedType.Name;
Console.WriteLine("Class in .Method2(): {0}", clss);
}
}

This will get the Type that first called TestClass. It prints:
TestStack.Class1
TestStack.Program
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
namespace TestStack
{
class Class1
{
public void Method1()
{
var obj = new TestClass();
obj.TestMethod1();
}
}
class TestClass
{
public void TestMethod1()
{
TestMethod2();
}
private void TestMethod2()
{
StackTrace st = new StackTrace();
Type calling = null;
foreach (var sf in st.GetFrames())
{
var type = sf.GetMethod().DeclaringType;
if (type != this.GetType())
{
calling = type;
break;
}
}
Console.WriteLine(calling);
}
}
class Program
{
static void Main(string[] args)
{
Class1 class1 = new Class1();
class1.Method1();
TestClass testClass = new TestClass();
testClass.TestMethod1();
}
}
}

Related

Why object a is not in current context?

using System;
namespace Testing
{
class Program
{
static void Main(string[] args)
{ }
}
public class A
{
public void method1()
{ }
}
public class B : A
{
public void method2()
{ }
}
public class Test
{
A a = new A();
a.method1();
}
}
Please paste this code in VS and Please explain me why it is not in current context?
Inside a class is not the right place to call most functions:
public class Test
{
A a = new A();
a.method1();
}
Just put stuff into the main function, wich is there specifically for that part of the programming:
static void Main(string[] args)
{
A a = new A();
a.method1();
}
you can not have statements directly in class.
public class Test
{
A a = new A();
a.method1(); // this is not possible.
}
please modify your class as below:
public class Test
{
public void InvokeMethodOnA()
{
A a = new A();
a.method1();
}
}
or like this;
public class Test
{
A a = new A();
public void InvokeMethodOnA()
{
a.method1();
}
}
You can call method in body of method (sounds strange, but I don't have a better explanation).
In your case you mix a definition of the class Test with a context of function. I hope code with comments will be more descriptive:
public class Test
{
// this is not a local variable, this is a definition of field with initialization
A a = new A();
// you try call method on field, but in context of class definition, which is prohibited
a.method1();
}

How to allow a different singleton class to be instantiated by passing different parameters into the constructor

I have a class in my project and I want to instantiate it only once by passing a specific parameter via the constructor, but when I pass different parameter it should instantiate a new one. How I can achieve this with the singleton design pattern? Or can you suggest another design pattern if it can't be achieved with a singleton?
class Program
{
static void Main()
{
SiteStructure s = SiteStructure.Instance;
}
}
public sealed class SiteStructure
{
static readonly SiteStructure _instance = new SiteStructure();
public static SiteStructure Instance
{
get
{
return _instance;
}
}
SiteStructure()
{
// Initialize.
}
}
You have to modify the way the _instance variable is initialised, making use of a function that accepts the parameter value that you want to pass in. Also, the _instance variable can no longer be readonly as it needs to be initialised inside of the new function.
[TestMethod]
public void CreateSingletonInstance()
{
SiteStructure s = SiteStructure.GetInstance("Abc123");
Debug.Print(s.Parameter); // outputs Abc123
SiteStructure s2 = SiteStructure.GetInstance("Is it really a singleton?");
Debug.Print(s2.Parameter); // outputs Is it really a singleton?
SiteStructure s3 = SiteStructure.GetInstance("Abc123");
Debug.Print(s3.Parameter); // outputs Abc123
Assert.AreNotEqual(s, s2); // Check to make sure they are different instances
Assert.AreEqual(s, s3); // Check to make sure they are the same instance
}
public sealed class SiteStructure
{
static Dictionary<string, SiteStructure> _siteStructures = new Dictionary<string, SiteStructure>();
static object _instance_Lock = new object();
public static SiteStructure GetInstance(string parameter)
{
if (!_siteStructures.ContainsKey(parameter))
{
lock (_instance_Lock)
{
if (!_siteStructures.ContainsKey(parameter))
{
_siteStructures.Add(parameter, new SiteStructure(parameter));
}
}
}
return _siteStructures[parameter];
}
private SiteStructure(string parameter)
{
// Initialize.
Parameter = parameter;
}
public string Parameter { get; set; }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
namespace Rextester
{
public class Program
{
public static void Main(string[] args)
{
var g = SiteStructure.Instance(4);
}
}
public sealed class SiteStructure {
public static SiteStructure Instance()
{ return new SiteStructure();
}
public static SiteStructure Instance (int x)
{ return new SiteStructure (x);
}
SiteStructure() { }
SiteStructure(int x) { Console.WriteLine("Hello"); }
}
}

C# | Assigning new class to interface object

Here is the code I currently have, the question follows after:
class Program
{
static void Main(string[] args)
{
var obj1 = new A();
obj1.DoIt();
obj1.SetFlyBehavior(new BehaviorB());
obj1.DoIt();
string input = Console.ReadLine();
}
};
class BaseOfA
{
protected ObjectBehavior behavior;
public void DoIt()
{
behavior.DoIt();
}
public void SetBehavior(ObjectBehavior ob) {
behavior = ob;
}
};
class A : BaseOfA {
public A() {
behavior = new BehaviorA();
}
}
interface ObjectBehavior {
void DoIt();
}
class BehaviorA : ObjectBehavior {
void ObjectBehavior.DoIt() {
Console.WriteLine("Behavior: A");
}
}
class BehaviorB : ObjectBehavior {
void ObjectBehavior.DoIt() {
Console.WriteLine("Behavior: B");
}
}
Now my question is, in this case, how am I going to make it work so that I can assign both BehaviorA and BehaviorB to instance obj1 as long as they implement ObjectBehavior?
You are calling obj.SetFlyBehaviour this method is not defined anywhere. The method you define on BaseOfA is called SetBehaviour. Once that is fixed the code you gave compiles fine for me

Can you create a generic method or property name which resolves from a string input?

Example:
String name = "setMethodName";
class Test
{
public void setName.[name] (Object o)
{
}
}
public static void Main()
{
Test test = new Test();
test.setMethodName(new Object());
}

c#: Calling common method of stored references to class objects from object[] array

Is using a switch on object types really the main way of calling a common function of stored references to class objects? It doesn't have to be a 'object' value type.
using System;
public class MainClass { public void Main() { print "hello world"; } }
public class SubClassOne : MainClass { }
public class SubClassTwo : MainClass { }
public class Storer
{
public void Main() {
object[] objects = new object[2];
objects[0] = new SubClassOne();
objects[1] = new SubClassTwo();
for(i=0;i<2;i++)
{
switch(objects[i].GetType().ToString())
{
case: "SubClassOne":
SubClassOne subclass = objects[i];
subclass.Main();
break;
case: "SubClassTwo":
SubClassTwo subclass = objects[i];
subclass.Main(); //Could probably call after the switch
break;
}
}
}
}
Note: Code not parsed, so there may be serious errors.
"Stringly" typed object oriented code is such a bad idea. You (almost) never need to know the type of an object via a string.
Changing your "print" to Console.WriteLine and main to this works fine
MainClass[] stuff = new MainClass[2];
stuff[0] = new SubClassOne();
stuff[1] = new SubClassTwo();
foreach(var item in stuff)
{
item.Main();
}
If the problem is you are determined to use an array of object, AlexH has answered.
In that case, I suggest to use as keyword to perform a safe cast operation :
using System;
public class MainClass { public void Main() { print "hello world"; } }
public class SubClassOne : MainClass { }
public class SubClassTwo : MainClass { }
public class Storer
{
public void Main() {
object[] objects = new object[2];
objects[0] = new SubClassOne();
objects[1] = new SubClassTwo();
for(i=0;i<2;i++)
{
var myMainClass = objects[i] as MainClass;
if (myMainClass != null)
{
myMainClass.Main();
}
}
}
}
As wudzik said it should be even better to declare objects as a MainClass array
There are many ways of solving this in a nice way, depends on:
If you know types and there are not too much of them:
Use LINQ OfType<>(). For more details see MSDN
foreach (var item in objects.OfType<SubClassOne>())
{
item.Main();
}
foreach (var item in objects.OfType<SubClassTwo>())
{
item.Main();
}
If there are many types, just introduce common interface
interface ISharedApi
{
void Main();
}
class SubClassOne : ISharedApi
class SubClassTwo : ISharedApi
And implement this/mark each type by it, then you just need single loop:
var objects = new List<ISharedApi>();
objects.Add(new SubClassOne());
objects.Add(new SubClassTwo());
foreach (var item in objects)
{
item.Main();
}
You should implement a more object oriented solution. Instead of creating an array consisting of objects you should make MainClass abstract and define an abstract method Main. After that you should implement Main in you sublclasses.
In this way you can exchange your code to:
using System;
public abstract class MainClass { public abstract void Main(); }
public class SubClassOne : MainClass {
public override void Main() { print "SubClassOne, hello world"; }
}
public class SubClassTwo : MainClass {
public override void Main() { print "SubClassTwo, hello world"; }
}
public class Storer
{
public void Main() {
MainClass[] objects = new MainClass[2];
objects[0] = new SubClassOne();
objects[1] = new SubClassTwo();
foreach(MainClass mc in objects)
{
mc.Main();
}
}
}

Categories

Resources