c# - How to allow specific class call specific method - c#

In my code i need to allow only class EchoProcess call method GetStorePrivateData from class MainData.I thnk it not better way but in this code it work done.How should i do?
** In future class MainData will have more protected class and allow specific other class to call it.
internal sealed class EchoProcess : MainData
{
private EchoProcess()
{
}
public static string EchoPrivate(string someCondition)
{
var result = GetStorePrivateData<EchoProcess, Key>();
//Condition here >
return "";
}
private class Key
{
}
}
internal class MainData
{
protected MainData()
{
}
private static readonly List<string> StorePrivateData = new List<string>();
protected static List<string> GetStorePrivateData<TEcho, TKey>() where TEcho : class where TKey : class
{
return CheckAllowGetStorePrivateDataClassAccess<TEcho, TKey>() ? StorePrivateData : null;
}
private static bool CheckAllowGetStorePrivateDataClassAccess<TEcho, TKey>()
{
var thisClass = MethodBase.GetCurrentMethod().DeclaringType;
var echoProcessType = typeof(TEcho);
var isEchoProcess = echoProcessType.Name == "EchoProcess";
var keyType = typeof(TKey);
var isKey = keyType.Name == "Key";
var isEqualNameSpace = thisClass.Namespace.Equals(echoProcessType.Namespace) &&
keyType.Namespace.Equals(echoProcessType.Namespace);
var keyTypeFullName = $"{echoProcessType.FullName}+{keyType.Name}";
var isEqulaKeyTypeNameSpace = keyType.FullName.Equals(keyTypeFullName);
return isEqualNameSpace && isEqulaKeyTypeNameSpace && isEchoProcess && isKey;
}
}

In my code I need to allow only class EchoProcess call method GetStorePrivateData from class MainData.
Do not do any of this stuff with reflection or stack traces.
Both types are internal. They're in the same assembly. Mark the method you wish to restrict callers on as internal. Now any code in your assembly can call that method. Who cares? You wrote that code; if you don't like it, you can change it.
This is a problem that should be solved by communicating with the coders who are writing the assembly about what the correct protocols are for using assembly implementation details. This is an interpersonal team relationships problem, so don't try to solve it by writing code. Mark the method as internal, and if there's a call site that you don't like, then talk to the developer who wrote it during code review to find out why they thought that was a good idea.

In future class MainData will have more protected class and allow specific other class to call it.
Glad to hear it... the solution I provide below isn't ideal (e.g. you won't get any errors at compile time), and there are object models that are probably better suited for this.
In my code i need to allow only class EchoProcess call method GetStorePrivateData from class MainData.I thnk it not better way but in this code it work done.How should i do?
It is pretty easy to write code that inspects the call stack (you can obtain a copy with var s = new StackTrace() and walk the stack with s.GetFrames()). You can walk the call stack and see if EchoProcess was the caller or if the call came from somewhere else. Here is a simple example:
static public class CallPermissionHelper
{
static public bool IsAllowed<T>() where T : class
{
var callers = new StackTrace()
.GetFrames()
.Select
(
f => f.GetMethod().DeclaringType
);
var immediateCaller = callers.ElementAt(1);
var firstOutsideCaller = callers
.Skip(2)
.Where
(
t => t != immediateCaller
)
.FirstOrDefault();
return (firstOutsideCaller == typeof(T));
}
}
The logic is straightforward:
Obtain a list of callers, derived from the stack trace.
Ignore the first frame (which references the current code location, not very helpful)
Check the second frame to determine the class that called our helper class. In our case it will be MainData. We can ignore any stack frames from this class, e.g. if it is calling itself or using utility functions, since obviously it has permission to call itself.
Check the rest of the frames for any other classes, working down the stack. If the first class we run into is EchoProcess, we return true. In all other cases we return false.
Here is how to use it in your example:
internal sealed class EchoProcess : MainData
{
private class Key {}
public static string GetPrivateFromMainData()
{
return MainData.GetStorePrivateData<EchoProcess, Key>();
}
}
internal class MainData
{
public static string GetStorePrivateData<TEcho, TKey>() where TEcho : class where TKey : class
{
var allowed = CallPermissionHelper.IsAllowed<EchoProcess>(); //Magic!!!
return allowed ? "Allowed" : "Blocked";
}
}
public class Program
{
public static void Main()
{
var a = EchoProcess.GetPrivateFromMainData();
var b = MainData.GetStorePrivateData<object, object>();
Console.WriteLine("a={0}", a);
Console.WriteLine("b={0}", b);
}
}
Output:
a=Allowed
b=Blocked
See my code on DotNetFiddle

Related

Is there a better way in C# to reserve long variable name?

var test = Class1.Subclass1.Subclass2.PropertyNameWhichIsBigName
I have to use above in many places. How to avoid typing or save few key stroke? is there any shortcut in C#
Yes, you can use Namespace aliases:
https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/namespaces/using-namespaces
using ShortName = Class1.Subclass1.Subclass2;
And then
var test = ShortName.PropertyNameWhichIsBigName;
How about a function:
Func<typeOfProperty> someName = () => Class1.Subclass1.Subclass2.PropertyNameWhichIsBigName;
if you now call
var test = someName();
you would get your desired value without having to type the long chain of properties all the time.
Edit:
Just to be clear, if PropertyNameWhichIsBigName changes, someName() will return the new value.
You can use namespace aliasing and just call it in namespaces section in your code, and you can effectively use objects and functions all over the body #canton7 has already written example for that.
or you can use code blocks statements but you have to implement IDisposable, but this can limit your object calling section but you can get benefit fit automatic dispose.
class Class1
{
public class Subclass1
{
public class Subclass2 : IDisposable
{
public string PropertyNameWhichIsBigName { get; set; }
public void Dispose()
{
throw new NotImplementedException();
}
}
}
}
class Program
{
static void Main(string[] args)
{
using (Class1.Subclass1.Subclass2 obj = new Class1.Subclass1.Subclass2())
{
string propertiesValue = obj.PropertyNameWhichIsBigName;
}
}
}

c# Method redirect or overload (possibly with arguments)

I'm not sure if this is possible, but I'm essentially looking for a class constructor redirect.
An example of what I'm attempting:
public class Test
{
public Test() : TestFromOther();
//public Test() => TestFromOther();
public TestFromOther() { return 'this' with some stuff done here }
//another case might be => TestFromOther(defaultparam)
}
I'm trying to do this so that even if the base constructor is called, it redirects to my method.
(I don't want to just put a call to TestFromOther() inside the body of the constructor.. I'm specifically looking for the :TestFromOther() or => operator.. I've seen it before but for the life of me cannot remember how it's done)
EDIT: It's mostly for cleanliness and readability, thus having the Logger.GetCurrentClassLogger();
public class Logger {
private string _callerClass;
// obviously this doesn't function, but is the ideal end product
//public Logger() => GetCurrentClassLogger();
// Ideally I want the constructor to be this function and if a user, for
// whatever reason does call the empty constructor, it goes to this func
public Logger GetCurrentClassLogger() {
StackFrame[] sf = new StackTrace().GetFrames();
string callerName = "";
foreach (StackFrame f in sf) {
if (f == sf[0])
continue;
if (f.GetMethod().Name == ".ctor") {
callerName = f.GetMethod().ReflectedType.Name;
break;
}
callerName = f.GetMethod().Name;
break;
}
this._callerClass = callerName;
return this;
}
}
I trimmed this down about as far as I could for use as an example
You can "chain" constructors. it's not a redirection.
public class Test
{
public Test() : this("defaultParam") {}
public Test(string stringParam) { }
}
It will execute Test(string stringParam) first and then Test()
Edit per the comments and the edited question
static method is the way to achieve what you like:
public static Logger GetCurrentClassLogger() {...}
and the instantiation:
var logger = Logger.GetCurrentClassLogger(); // no new key word here
No, this is not possible. C# only allows you to call a base constructor or another constructor of the current class.
BTW the thing TestFromOther is also not a valid syntax, as it it is neither a method nor a constructor. Further, a constructor is not allowed to return anything.
The typical solution here would rather be to use a single constructor (possibly private such that it cannot be accessed from the outside) that does what you want. Or you may use helper methods for the initialization.

C# Invoking a method using reflection in a generic manner

I have two processes (A and B), both have a method Foo(SomeClass paramA, SomeOtherClass paramB).
The processes communicate using Windows Pipes (not WCF) and can send and receive messages of type:
public class PipeMessageArgs
{
public PipeMessageArgs(string i_MethodName, List<object> i_Args)
{
MethodName = i_MethodName;
Args = i_Args;
}
public string MethodName { get; private set; }
public List<object> Args { get; private set; }
}
When calling Foo on A, I want to invoke Foo on B, with the same values.
This is the calling code in A:
public void Foo(SomeClass paramA, SomeOtherClass paramB)
{
var args = new List<object> { paramA, paramB };
m_Server.PushMessage(new PipeMessageArgs(MethodBase.GetCurrentMethod().Name, args));
}
This is the invoking code in B:
void ClientOnReceiveMessage(NamedPipeConnection i_Connection, object i_Message)
{
var pipeMessageArgs = i_Message as PipeMessageArgs;
GetType().GetMethod(pipeMessageArgs.MethodName).Invoke(this, pipeMessageArgs.Args.ToArray());
}
But as you can see, I have to manually create a list of parameters for each call so if I forget a parameter or get the order wrong, things will not work. Given that I cannot use reflection to get the values, and I do not want to use the profiler (performance is an issue), what is the best way to make it more generic?
Edit: I cannot use WCF for too many reasons (actually, I am moving away from WCF). I am using pipes, namely PipeStream.
Edit2: What I want is a solution that does not rely on manually creating arrays of parameters; something that can create this array automatically for me.
I ended up using RealProxy. RealProxy is mainly used for remoting but can allow you to create proxy for classes. You can then add functionality before each method call (also properties calls). I used this very nice blog post to implement it.
This is my proxy:
public class InvokingProxy : RealProxy
{
private readonly INamedPipe _namedPipe;
InvokingProxy(object i_Target, INamedPipe i_NamedPipe) : base(i_Target.GetType())
{
_namedPipe = i_NamedPipe;
}
public override IMessage Invoke(IMessage i_Msg)
{
var methodCall = i_Msg as IMethodCallMessage;
if (methodCall != null)
{
return HandleMethodCall(methodCall);
}
return null;
}
IMessage HandleMethodCall(IMethodCallMessage i_MethodCall)
{
_namedPipe.PushMessage(new PipeMessageArgs(i_MethodCall.MethodName, i_MethodCall.InArgs));
return new ReturnMessage(null, null, 0, i_MethodCall.LogicalCallContext, i_MethodCall);
}
public static T Wrap<T>(T i_Target, INamedPipe i_NamedPipe) where T : MarshalByRefObject
{
return (T)new InvokingProxy(i_Target, i_NamedPipe).GetTransparentProxy();
}
}
I use i_MethodCall.InArgs to get the in-arguments, that's the hear of the issue. Also notice how HandleMethodCall uses the pipe to push a message instead of actually calling the requested method. This means that my 'API' class is actually just empty methods with no implementation (I can always add more implementation there and invoke the method before/after the pipe action):
class Api : MarshalByRefObject, IApi
{
public void Foo(SomeClass paramA, SomeOtherClass paramB)
{
}
public void Bar(SomeClassX paramA, SomeOtherClassY paramB)
{
}
}
}
Also, as a requirement of RealProxy. the class has to inherit from MarshalByRefObject which was fine by me as it has no other functionality. Read more about it in the blog post I linked.

Is there any way to bypass the private keyword?

I have a bunch of code that is used for debugging purposes. Therefore, I surround it with:
#if DEBUG
#endif
The issue is that this debugging code needs to output private variables from other classes to a file. I can sneak the debug code into each class but that makes existing code more confusing because I have debug code mixed with real code. I can put all the debug code into another class but that would mean that I would have to make private variables in classes public.
Is there any way to ignore the private keyword for the purposes of debugging code? I can use public getters but that defeats the purpose of not making the real code more confusing.
Is it possible to make them internal instead of private?
Use the dynamic keyword:
dynamic foo = yourObjectWithPrivateFields;
int privateValue = (int)foo.yourPrivateField;
Use Reflection: typeof(YourObject).GetField(fieldName, bindFlags).GetValue(yourObjectWithPrivateFields);
Using Reflection as thefiloe suggests might be the best way to go for this particular problem.
Just to illustrate one way to address the code organization problem that the OP asked about, I've provided an example of an alternate approach. This may not be the ideal way to solve the problem of wanting to log data from private members for debugging purposes, but it demonstrates organizing code using partial classes as well as using a nested class in order to provide external code with a way to access private members.
// This MyClass code goes into a MyClass.cs file
public partial class MyClass
{
private int fieldA;
private string fieldB;
private decimal fieldC;
public MyClass(int a, string b, decimal c)
{
this.fieldA = a;
this.fieldB = b;
this.fieldC = c;
}
}
// This additional code for MyClass goes into a
// separate MyClass.debug.cs file
#if DEBUG
partial class MyClass : IDebugAccessible
{
public IDebugAccessor GetDebugAccessor()
{
return new DebugAccessor(this);
}
// The MyClass.DebugAccessor nested class has access to
// private members of MyClass.
private class DebugAccessor : IDebugAccessor
{
private MyClass instance;
public DebugAccessor(MyClass instance)
{
this.instance = instance;
}
public IEnumerable<KeyValuePair<string, object>> Values
{
get
{
return new Dictionary<string, object>
{
{ "fieldA", instance.fieldA },
{ "fieldB", instance.fieldB },
{ "fieldC", instance.fieldC },
};
}
}
}
}
#endif
// The intention behind creating these interfaces is to define
// a standard way to access values from different types
// for debugging purposes. This is just a simple example.
// These interfaces would go into their own .cs file.
public interface IDebugAccessor
{
IEnumerable<KeyValuePair<string, object>> Values { get; }
}
public interface IDebugAccessible
{
IDebugAccessor GetDebugAccessor();
}

C# Instance Class with Static Methods - using methods differently between threads

Hello I have this code here:
Memory.OpenProcess(Processes[0].Id);
Hook.Apply(........);
Memory and Hook are both non-static classes, and openprocess and Apply are both static methods within those classes.
However, the problem is, for each instance of my Memory or Hook, I want to have a different process opened, and a different Hook applied.
What I want to do is:
Memory newMemory = new Memory();
newMemory.OpenProcess(processes[1].Id);
Hook newHook = new Hook();
newHook.Apply(....);
But of course I cannot do this because the methods are static and not particular to each instance.
I cannot change the static methods because these methods are coming from a dll in which I do not have access to the source code.
Any ideas?
**Edit: I want to do this so I can avoid having to rehook the process every time a new thread comes along that is working with a different process.
It seems that you cannot do that by design. The implementor of the classes from the dll you are consuming might have explicitly want to avoid the functionality you are trying to achieve.
You can load each thread in different AppDomain, that would give you different static methods.
Also, ThreadStaticAttribute might be helpful for you. Don't sure if it fits you, but give it a look.
Upd: More info about using AppDomains. Lets assume, that you have 3-rd party class Memory defined as follows. (And you cannot change it, and it uses inner static variables)
// Cannot be changed
public class Memory
{
static int StaticId;
public static void OpenProcess(int id)
{
StaticId = id;
}
public static int GetOpenedId()
{
return StaticId;
}
}
You can write a wrapper, deriving from MarshalByRefObject (that's important):
class MemoryWrap : MarshalByRefObject
{
public void OpenProcess(int id)
{
Memory.OpenProcess(id);
}
public int GetOpenedId()
{
return Memory.GetOpenedId();
}
}
So if you create instances of MemoryWrap not by new keyword, but using AppDomain.CreateInstanceAndUnwrap in another domain, each instance would have it's own static contexts. Example:
class Program
{
static void Main(string[] args)
{
var type = typeof(MemoryWrap);
var domain1 = AppDomain.CreateDomain("Domain 1");
var memory1 = (MemoryWrap)domain1.CreateInstanceAndUnwrap(type.Assembly.FullName, type.FullName);
var domain2 = AppDomain.CreateDomain("Domain 2");
var memory2 = (MemoryWrap)domain2.CreateInstanceAndUnwrap(type.Assembly.FullName, type.FullName);
memory1.OpenProcess(1);
memory2.OpenProcess(2);
Console.WriteLine(memory1.GetOpenedId());
Console.WriteLine(memory2.GetOpenedId());
Console.ReadLine();
}
}
It would print:
1
2
PS: in that example I didn't do the clean up just for readability (unloading domains with AppDomain.Unload() and other things). Don't forget to do it in you code. + There is some mess with lifetime of objects in another domain, but it is next level of problems)))
I'm not sure I fully understand the question, but I will try to answer anyways.
You could define two new classes:
public class MemoryInstance : Memory
{
private var m_instanceProcessId;
public MemoryInstance(var processId) : base()
{
m_instanceProcessId = processId;
}
public void OpenProcess()
{
Memory.OpenProcess(m_instanceProcessId);
}
}
public class HookInstance: Hook
{
private var m_hookId;
public HookInstance(var hookId) : base()
{
m_hookId = hookId;
}
public void Apply()
{
Hook.Apply(m_hookId);
}
}
Then in your code you could call:
public static void Main(String[] args)
{
MemoryInstance newMemory = new MemoryInstance(processes[1].Id);
HookInstance newHook = new HookInstance(hookId);
newMemory.OpenProcess();
newHook.Apply();
}
See , if the API writers are doing that it must be for some reason , you should consult your API writers for he reason or if they can provide you something at instamnce level.
BUT for circumvent your situation , you can use the method provided The_Smallest above.
or you can make use of Reflection as shown below
Memory m = Activator.CreateInstance("Your Dll Name", true) , here true stands for the calling of private constructor.
But i am not convinced , you should do it , you first call to the API writer to get the reason of doing this.

Categories