How to get Attribute value of calling method - c#

I would like to dynamically get the value of the attribute on method, which could be anywhere in the calling hierarchy.
Now I have found the solution using StackTrace's FrameCount and GetFrame. But it's not dynamic
Rollback.cs
namespace AnotationTest
{
[AttributeUsage(AttributeTargets.Method, Inherited = false, AllowMultiple = false)]
class RollbackAttribute: Attribute
{
public Guid RollbackGuid { get; set; }
public RollbackAttribute()
{
RollbackGuid = Guid.NewGuid();
}
}
}
Program.cs
class Program
{
static void Main(string[] args)
{
Test();
}
[RollbackAttribute]
public static void Test()
{
Test1();
}
public static void Test1()
{
Test2();
}
public static void Test2()
{
Test3();
}
public static void Test3()
{
Test4();
}
public static void Test4()
{
var framecount = new StackTrace().FrameCount;
System.Reflection.MethodBase method = new StackTrace().GetFrame(framecount-2).GetMethod();
RollbackAttribute rollback = (RollbackAttribute)method.GetCustomAttributes(typeof(RollbackAttribute), true)[0];
}
}
I would like to have a solution to get the attribute value from the Test4 method. But without using StackTrace which is used now. Thank you for any help.

What you want to use is CallContext and its Set/GetLogicalData methods that serves the purpose of traversing data from caller to "callee" without the need to use method parameters or attributes.
class Program
{
static void Main(string[] args)
{
CallContext.LogicalSetData("rollbackGuid", Guid.NewGuid());
Test();
Console.ReadKey();
}
public static void Test()
{
Test1();
}
//[RetryOnExceptionAttribute]
public static void Test1()
{
Test2();
}
public static void Test2()
{
Test3();
}
public static void Test3()
{
Console.WriteLine($"Current thread id: {Thread.CurrentThread.ManagedThreadId}");
Task.Run((() => { Test4(); }));
}
public static void Test4()
{
Console.WriteLine($"Current thread id: {Thread.CurrentThread.ManagedThreadId}");
Console.WriteLine($"Rollback guid: {Rollback.CurrentGuid}");
}
}
static class Rollback
{
public static Guid CurrentGuid => (Guid)CallContext.GetData("rollbackGuid");
}

Related

How can use Extension Method in MoonSharp?

ExtensionType in MoonSharp Unity has cache issue?
public static class ExtMethods
{
public static void Test1(this MyClass c) { Debug.Log("test1"); }
public static void Test2(this MyClass c) { Debug.Log("test2"); }
public static void Test3(this MyClass c) { Debug.Log("test3"); }
}
public class MyClass
{
public MyClass() { }
}
public class Scripts
{
Script _script = new Script();
string _myScript =
"local a = Class()" +
"a.Test1()" +
"a.Test2()" +
"a.Test3()" +
public void InitScript()
{
UserData.RegisterExtensionType(typeof(ExtMethods));
UserData.RegisterType(typeof(MyClass));
_script.Globals["Class"] = typeof(MyClass)
_script.DoString(_myScript);
}
}
it only cache just first method of ExtensionType
local a = Class.__new()
a.Test1() -- access success
a.Test2() -- failed
a.Test3() -- failed

How to pass parameters from main method to another class

How do I pass the parameters from main method to another class?
I have done like this. Is this right approach?
namespace classA
{
class Program
{
public static void Main(string[] args)
{
string abc= new string {"HELLO"};
Console.WriteLine("My result: {0}", ClassB(abc));
Console.Read();
}
public static string ClassB(string abc)
{
//code
return xyz;
}
}
}
well in the code you posted you have only one class with two methods but in principle yes, this would be one way:
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
string abc = "HELLO";
Console.WriteLine("My result: {0}", ClassB(abc));
Console.Read();
}
public static string ClassB(string abc)
{
return abc;
}
}
}
My result: HELLO
If you have your second method really in another STATIC class:
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
string abc = "HELLO";
Console.WriteLine("My result: {0}", myfuncclass.ClassB(abc));
Console.Read();
}
}
static class myfuncclass
{
public static string ClassB(string abc)
{
return abc;
}
}
}
My result: HELLO
And if your second method is NOT in a static class and your method is NOT static you have to create an instance of the class first and then call your method on this object:
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
string abc = "HELLO";
myfuncclass test = new myfuncclass();
Console.WriteLine("My result: {0}", test.ClassB(abc));
Console.Read();
}
}
public class myfuncclass
{
public string ClassB(string abc)
{
return abc;
}
}
}

How to call a class method from another class instance

I'm new to C#, I'm in doubt about how to make this work:
namespace Core {
public class A{
private reandonly string _var;
public A(string var){
_var=var
}
public GetValue() => return _var;
}
}
using System;
namespace Core.Resources {
public static class B{
public static void DoSomething(){
Console.Writeline($"{A.GetValue()}");
}
}
}
public class C{
static void Main(string args[]){
A a = new A("name");
a.Resources.B.DoSomething();
}
}
A is in main folder, B is in Main/Resources folder, together they make a classlib, Program.cs is using this lib. Is there a way to make this work?
If you write a.Resources you are basically trying to retrieve the member Resources of the class A, which is obviously not defined. Since B is a static class defined in the Core.Resources namespace, all you have to do is to change your code as follows:
public class C
{
public static void Main(string args[])
{
A a = new A("A");
Core.Resources.B.DoSomething();
}
}
or, alternatively, if you don't want to reference the namespace every time:
using Core.Resources;
public class C
{
public static void Main(string args[])
{
A a = new A("A");
B.DoSomething();
}
}
Note that if yuu explicitly define a public constructor for A that accepts one or more arguments, the default parameterless constructor is no more available... hence you have to pass a string to the A constructor if you don't want to see an error in your console. Alternatively, you have to rewrite your A class so that it implements a default parameterless compiler, for example:
public class A
{
private reandonly String _var;
public A() : this(String.Empty) { }
public A(String var)
{
_var = var;
}
}
EDIT AS PER OP COMMENTS AND QUESTION CHANGES
public class A
{
private reandonly String _var;
public String Var
{
get { return _var; }
}
public A(String var)
{
_var = var;
}
}
public static class B
{
public static void DoSomething(String text)
{
Console.Writeline(text);
}
}
public class C
{
public static void Main(string args[])
{
A a = new A("name");
B.DoSomething(a.Var);
}
}

property injection using autofac 3.1.1

i am trying to inject through property in the following service, if I try constructor injection it works but I want to do property injection, what am I missing?
public class SodaService
{
public ISoda _s;
//public SodaService(ISoda s)
//{
// _s = s;
//}
public string GetSoda()
{
return _s.SodaName;
}
}
//Soda Class implementing ISoda
public class Soda : ISoda
{
public string SodaName
{
get { return "Default Soda"; }
}
}
public interface ISoda
{
string SodaName { get; }
}
//Main calling program
class Program
{
static void Main(string[] args)
{
var container = GetContainer();
SodaService s=container.Resolve<SodaService>();
Console.Write(s.GetSoda());
Console.Read();
}
private static IContainer GetContainer()
{
var builder = new ContainerBuilder();
builder.RegisterType<Soda>().As<ISoda>();
builder.RegisterType<SodaService>()
.PropertiesAutowired();
var container = builder.Build();
return container;
}
}
EDIT:
The above was solved and i have one more question....
How can i make something like this work, i do not want to use
s = container.Resolve< ISodaService >();
and instead the dependencies should be automatically injected when i run the program
class Program
{
public static ISodaService s { get; set; }
static void Main(string[] args)
{
SetUpContainer();
//s = container.Resolve<ISodaService>();
Console.Write(s.GetSoda());
Console.Read();
}
private static void SetUpContainer()
{
var builder = new ContainerBuilder();
builder.RegisterType<Soda>().As<ISoda>();
builder.RegisterType<SodaService>().As<ISodaService>().PropertiesAutowired();
builder.Build();
}
}
The problem you have is Main method is static. Instanciate a class of Program and use is as non static class
class Program
{
public ISodaService s { get; set; }
static void Main(string[] args)
{
var resolver=SetUpContainer();
var instance=resolver.Resolve<Program>();
instance.Execute(args);
}
public void Execute(string[] args)
{
Console.Write(s.GetSoda());
Console.Read();
}
private Autofac.IContainer void SetUpContainer()
{
var builder = new ContainerBuilder();
builder.RegisterType<Soda>().As<ISoda>();
builder.RegisterType<SodaService>().As<ISodaService>().PropertiesAutowired();
builder.RegisterType<Program>().PropertiesAutowired();
return builder.Build();
}
}

C# Each instance of class needs different method

I have a static class with number of different methods.
I have another class, and with each instance of this class, I would like it to have a method which calls one of the methods in the static class. For each instance, I want be able to specify which of the methods it will use via the constructor of this class.
Is there a simple way to do this? Should I be using delegates/interfaces?
Do the methods all have the same signature? If so, a delegate would certainly be a good approach... although it wouldn't restrict the caller to passing in a method group from the static class. If that's not a problem, here's a sample:
using System;
public static class TestMethods
{
public static void Foo(int x)
{
Console.WriteLine("Foo " + x);
}
public static void Bar(int x)
{
Console.WriteLine("Bar " + x);
}
}
public class DummyClass
{
private readonly Action<int> action;
public DummyClass(Action<int> action)
{
this.action = action;
}
public void CallAction(int start, int end)
{
for (int i = start; i < end; i++)
{
action(i);
}
}
}
class Test
{
static void Main()
{
DummyClass d1 = new DummyClass(TestMethods.Foo);
DummyClass d2 = new DummyClass(TestMethods.Bar);
d1.CallAction(2, 4);
d2.CallAction(3, 7);
}
}
Here is what you are looking for:
public delegate void MyStaticMethodInvoker(params object[] values);
public class TestStatic
{
public static void TestMethod1(params object[] values)
{
Console.WriteLine("TestMethod1 invoked");
}
public static void TestMethod2(params object[] values)
{
Console.WriteLine("TestMethod2 invoked");
}
public static void TestMethod3(params object[] values)
{
Console.WriteLine("TestMethod3 invoked");
}
}
public class TestClass
{
private MyStaticMethodInvoker _targetMethod;
public TestClass(MyStaticMethodInvoker targetMethod)
{
_targetMethod = targetMethod;
}
public void CallTargetedStaticMethod()
{
_targetMethod.Invoke(1,2,3,4);
}
}
And then you can create instances of TestClass and in constructor define target static method:
TestClass tc1 = new TestClass(new MyStaticMethodInvoker(TestStatic.TestMethod1));
tc1.CallTargetedStaticMethod();
TestClass tc2 = new TestClass(new MyStaticMethodInvoker(TestStatic.TestMethod2));
tc2.CallTargetedStaticMethod();
TestClass tc3 = new TestClass(new MyStaticMethodInvoker(TestStatic.TestMethod3));
tc3.CallTargetedStaticMethod();

Categories