How to call a class method from another class instance - c#

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);
}
}

Related

Need to call a static factory method in a generic method (Error CS0119)

I need to call a static factory method from a generic method.
Some solution suggest using reflection. Is there no other way to do so? Why C# has this constraint?
Here is my minimal example:
using System;
public class MainClass
{
public static void Main(string[] args)
{
A a = Get<A>("apiA");
B b = Get<B>("apiB");
}
public static T Get<T>(string url)
{
string json = "{}"; // answer received from api
return T.Factory(json); // error CS0119: 'T' is a type parameter, which is not valid in the given context
}
}
class A {
// public field
public static A Factory(string json)
{
// need to do more A-specific thing here
return NotUnderMyControl.FromJson<A>(json);
}
}
class B {
// public fields
public static B Factory(string json)
{
// need to do more B-specific thing here
return NotUnderMyControl.FromJson<B>(json);
}
}
static class NotUnderMyControl {
public static T FromJson<T>(string json) where T : new()
{
return new T();
}
}
You may want to make the methods common in the interface and change static methods to instance methods.
public class MainClass
{
public static void Main(string[] args)
{
A a = Get<A>("apiA");
B b = Get<B>("apiB");
}
static class FactoryCache<T> where T : IFactory<T>, new()
{
public static readonly T Instance = new T();
}
public static T Get<T>(string url) where T : IFactory<T>, new()
{
string json = "{}"; // answer received from api
return FactoryCache<T>.Instance.Factory(json);
}
}
public interface IFactory<T>
{
T Factory(string json);
}
class A : IFactory<A>
{
public A Factory(string json)
{
return NotUnderMyControl.FromJson<A>(json);
}
}
class B : IFactory<B>
{
public B Factory(string json) {
return NotUnderMyControl.FromJson<B>(json);
}
}

Static class derive from base change member

In C# a static class can not derive from any other class besides object.
Currently I have this base class:
public static class BaseModule
{
public static string UsedSource {get; set;}
public static Write(string text)
{
OtherStaticClass.Log(UsedSource, text);
}
}
Now, depending on which class I'm using, I want to change UsedSource.
// this does not work
internal static class ModuleA : BaseModule
{
static ModuleA(){
UsedSource = "A" // just an example
}
}
// this does not work
internal static class ModuleB : BaseModule
{
static ModuleB(){
UsedSource = "B" // just an example
}
}
Supposed to be called like this
ModuleA.Write("Hi");
ModuleB.Write("Hi");
This approach does not work because a static class cannot derive from anything else than object.
Is there any other way to change the property?
You have a lot of static classes going on here and I'm not entirely sure they're necessary. My example does not use static classes other than for the OtherStaticClass reference you have. I understand this may not be quite what you're looking for; many ways to skin this cat.
public abstract class BaseModule
{
public string UsedSource { get; set; }
public void Write(string text)
{
OtherStaticClass.Log(UsedSource, text);
}
}
public class ModuleA : BaseModule
{
public ModuleA()
{
UsedSource = "A";
}
}
public class ModuleB : BaseModule
{
public ModuleB()
{
UsedSource = "B";
}
}
To get your output then, you just need to create new instances of ModuleA and ModuleB.
var moduleA = new ModuleA();
var moduleB = new ModuleB();
moduleA.Write("Hi");
moduleB.Write("Hi");
Using a static class means using a singleton. Singletons defeat the purpose of tracking the effective dependencies of your classes.
Anyway, you can approach the problem by refactoring your code and using a factory:
In this case, just drop the static keyword and let the class be inheritable (you have to add the appropriate virtual keywords to allow proper inheritance):
public class BaseModule
{
public string UsedSource {get; set;}
public Write(string text)
{
OtherStaticClass.Log(UsedSource, text);
}
}
Then, add an additional class which holds the reference (I gave useless names, focus on the purpose):
public static class MySingleton
{
public static BaseModule _Module;
public static BaseModule Module
{
get
{
return _Module;
}
}
public static void ChangeImplementation (BaseModule module)
{
// do your checks here
_Module = module;
}
}
This way wou can achieve what you ask.
As you can see, this code has several issues, among them it's important to note that this code has global side effects and is not thread safe.
A better approach is to have drop the singleton entirely, and pass the BaseModule class (that can be inherited) as an argument of methods/constructors when needed.
I don't see that you need more than one static class. Instead separate the logic into methods in one static class.
public static class Module
{
private const string SourceA = "A";
private const string SourceB = "B";
public static WriteA(string text)
{
Write(SourceA, text);
}
public static WriteB(string text)
{
Write(SourceB, text);
}
private static Write(string source, string text)
{
OtherStaticClass.Log(source, text);
}
}
Then instead of
ModuleA.Write("Hi");
ModuleB.Write("Hi");
you'd do
Module.WriteA("Hi");
Module.WriteB("Hi");
If you can't change the BaseModule class, you can use it with other state and recover state after using:
public static class BaseModule
{
public static string UsedSource {get; set;}
public static Write(string text)
{
OtherStaticClass.Log(UsedSource, text);
}
}
internal class Writer : IDisposable
{
string _lastSource;
public Writer(string source)
{
_lastSource = BaseModule.UsedSource;
BaseModule.UsedSource = source;
}
public void Dispose()
{
BaseModule.UsedSource = _lastSource;
}
}
internal abstract class Module
{
public abstract Source { get; };
public void Write(string text)
{
using (var writer = new Writer(Source))
{
BaseModule.Write(text);
}
}
}
internal class ModuleA : Module
{
public override Source => "A";
}
internal class ModuleB : Module
{
public override Source => "B";
}
But you must ensure thread safety.
If you can change the BaseModule class:
public static class BaseModule
{
public static Write(string text, string source)
{
OtherStaticClass.Log(source, text);
}
}
internal abstract class Module
{
public abstract Source { get; };
public void Write(string text)
{
BaseModule.Write(text, Source);
}
}
internal class ModuleA : Module
{
public override Source => "A";
}
internal class ModuleB : Module
{
public override Source => "B";
}

How to override a static method from a DLL Export

I want to override a static method from a DLL Export
public class Export {
[DllExport] public static string plugin_name() { return Plugin.Instance.plugin_name(); }
}
public class Plugin<T> where T: Plugin<T>, new()
{
private static readonly Lazy<T> val = new Lazy<T>(() => new T());
public static T Instance { get { return val.Value; } }
protected Plugin() { }
public new static string plugin_name() { }
}
}
so these classes are in a dll file now I want that people who use the dll only do that in the main class.
public class Main : Plugin<Main> {
public override string plugin_name() {
return "a test plugin";
}
}
I have tested it for hours but failed.
You can not override static methods. You need to make a virtual or abstract instance method.
public abstract class Plugin<T> where T : new()
{
private static readonly Lazy<T> val = new Lazy<T>(() => new T());
public static T Instance { get { return val.Value; } }
protected Plugin() { }
public abstract string plugin_name();
}
public class Main : Plugin<Main> {
public override string plugin_name() => "a test plugin";
}
To make the method plugin_name static also does not make much sense, since you anyway create a singleton instance.
You can check out the code here.

Intelligent Generic Static Method

I wrote C# code as described below that inherits a class from a generic class with static methods. I want to call the child class for its static methods (inherited from the base class) without having to specify the type.
EDITED! More "real" code
public class Rec
{
public string Name { get; set; }
public override string ToString() { return this.Name; }
public virtual void Load() { /* HERE IT READS A TEXT FILE AND LOAD THE NAME */ }
}
public class BaseClass<T> : Rec
{
public T Argument { get; set; }
public override void Load() { /* NOW IT LOADS ALSO THE ARGUMENT */ }
public static H Method<H>() where H : Rec, new()
{
H iH = new H();
iH.Load();
iH.Name += " " + iH.Argument.ToString();
return iH;
}
}
public class Child : BaseClass<string> { }
public class SomeOtherClass
{
public void Test()
{
Child i = Child.Method();
//instead of Child.Method<Child>();
}
}
So, instead of having to call method<h>() i'd like to just call method(), so the code should assume that "h" is the caller type. Like in:
How can I do it?
Static methods are not inherited in C#
See this answer for an idea of a potential implementation: Stack Overflow whats-the-correct-alternative-to-static-method-inheritance
You could change method<h> to method and make it an instance method:
public class BaseClass<T> where T, new()
{
public T method() { /* RETURN SOMETHING */ }
}
And then call it as follows:
public class ABC : Child
{
public void Test()
{
var iABC = this.method();
}
}

C# How to treat static class as a variable

I have a static Class and within it I have multiple public static attributes. I treat this class as my global class.
However now I need to treat this class as a variable so that I can pass it to a method of another class for processing..
I can't instantiate this class.. So in effect I can only assign the variables inside this class.
Is my understanding correct or am I missing something?
public static class Global
{
public const int RobotMax = 2;
// GUI sync context
public static MainForm mainForm;
public static SynchronizationContext UIContext;
// Database
public static Database DB = null;
public static string localDBName = "local.db";
public static Database localDB = null;
public static Database ChangeLogDB = null;
public static string changeLogDBName = "ChangeLog.db";
}
Let say I have a class like this, and I need to somehow keep a copy of this in another class maybe
public static class Global_bk
{
public const int RobotMax = 2;
// GUI sync context
public static MainForm mainForm;
public static SynchronizationContext UIContext;
// Database
public static Database DB = null;
public static string localDBName = "local.db";
public static Database localDB = null;
public static Database ChangeLogDB = null;
public static string changeLogDBName = "ChangeLog.db";
}
I need to copy the contents from Global to Global_bk.
And after that I need to compare the contents of the two classes in a method like
static class extentions
{
public static List<Variance> DetailedCompare<T>(T val1, T val2)
{
List<Variance> variances = new List<Variance>();
FieldInfo[] fi = val1.GetType().GetFields();
foreach (FieldInfo f in fi)
{
Variance v = new Variance();
v.Prop = f.Name;
v.valA = f.GetValue(val1);
v.valB = f.GetValue(val2);
if (!v.valA.Equals(v.valB))
variances.Add(v);
}
return variances;
}
}
class Variance
{
string _prop;
public string Prop
{
get { return _prop; }
set { _prop = value; }
}
object _valA;
public object valA
{
get { return _valA; }
set { _valA = value; }
}
object _valB;
public object valB
{
get { return _valB; }
set { _valB = value; }
}
}
So on my main form, how do I go about calling the compare method and passing the static Global class inside?
example: extentions.DetailedCompare(Global, Global_bk) ? Of course this would give me an error because I cant pass a type as a variable.
Please help me, this is driving me nuts...
How about the singleton pattern ? You can pass reference to shared interface (IDoable in exable below) and still have just one instance.
I.E.:
public interface IDoable {
int Value { get; set; }
void Foo();
}
public static class DoableWrapper {
private MyDoable : IDoable {
public int Value { get;set; }
public void Foo() {
}
}
private static IDoable s_Doable = new MyDoable();
public static IDoable Instance {
get { return s_Doable; }
}
}
Singleton is the way to go here. You can do it like this:
internal class SomeClass
{
private static SomeClass singleton;
private SomeClass(){} //yes: private constructor
public static SomeClass GetInstance()
{
return singleton ?? new SomeClass();
}
public int SomeProperty {get;set;}
public void SomeMethod()
{
//do something
}
}
The GetInstance Method will return you a SomeClass object that you can edit and pass into whatever you need.
You can access the members with classname.membername.
internal static class SomeClass
{
public static int SomeProperty {get;set;}
public static void SomeMethod()
{
//do something
}
}
static void main()
{
SomeClass.SomeProperty = 15;
SomeClass.SomeMethod();
}
The only way you are going to obtain a variable with the "class" information is using reflection. You can get a Type object for the class.
namespace Foo {
public class Bar
{
}
}
Type type = Type.GetType("Foo.Bar");
Otherwise, if you are really describing a class "instance" then use an object and simply instantiate one.
C# offers no other notation for class variables.

Categories