I've declared a list in a class. I want to access the list from another class. How can I access the list from a module of another class?
// ClsUser.cs
namespace WebLll.ApiPayment.BusinessObject
{
public class ClsUser
{
Data.MyEntity db = new Data.MyEntity("MyEntity1");
public List<Data.GetPaymentRslt> BRIlstTxn = db.GetPayment(obj.PaymentCode, dtFrom, dtTo, obj.PaymentMode).ToList();
//... remaining code
}
}
// clsWebLllAPI.cs
namespace WebLll.ApiPayment.BusinessObject
{
public class clsWebLllAPI : clsBaseApi
{
public void Initialize(api_rule_setup obj)
{
// access the BRIlstTxn here
}
}
}
Since the list is public you can simply create an instance of the class and access it like follow,
ClsUser clsuser=new ClsUser();
List<Data.GetPaymentRslt> mylist=clsuser.BRIlstTxn; // Simply access PUBLIC field
From MSDN
Accessing a field in an object is done by adding a period after the object name
But as good programming practice,I suggest you to use Accessors over making a field public (need to know why, check this)
Suggestion code :
// ClsUser.cs
namespace WebLll.ApiPayment.BusinessObject
{
public class ClsUser
{
Data.MyEntity db = new Data.MyEntity("MyEntity1");
private List<Data.GetPaymentRslt> BRIlstTxn = db.GetPayment(obj.PaymentCode, dtFrom, dtTo, obj.PaymentMode).ToList();
// Only GET . Provide protection over setting it
public List<Data.GetPaymentRslt> brIlstTxn{
get
{
return BRIlstTxn;
}
}
//... remaining code
}
}
// clsWebLllAPI.cs
namespace WebLll.ApiPayment.BusinessObject
{
public class clsWebLllAPI : clsBaseApi
{
public void Initialize(api_rule_setup obj)
{
ClsUser clsuser=new ClsUser();
List<Data.GetPaymentRslt> mylist=clsuser.brIlstTxn; // Now you are accessing GET accesor rather than field directly
}
}
}
You can use Dot, member access operator to access public/internal/protected data member (list) of other class.
namespace WebLll.ApiPayment.BusinessObject
{
public class clsWebLllAPI : clsBaseApi
{
public void Initialize(api_rule_setup obj)
{
ClsUser clsUser = new ClsUser ();
var lst = clsUser.BRIlstTxn;
}
}
}
Related
Let's say that I am using a library that I have no control over whatsoever. This library exposes service that requires argument of certain class. Class is marked as sealed and has no interface.
tl;dr: How can I reimplement sealed class as interface?
Code example:
using System;
namespace IDontHaveControlOverThis
{
// Note no interface and the class is being sealed
public sealed class ArgumentClass
{
public String AnyCall() => "ArgumentClass::AnyCall";
}
public sealed class ServiceClass
{
public String ServiceCall(ArgumentClass argument) => $"ServiceClass::ServiceCall({argument.AnyCall()})";
}
}
namespace MyCode
{
// Composite pattern, basically I need: "is a ArgumentClass"
// Obviously doesn't work - can't extend from sealed class
public class MyArgumentClass : IDontHaveControlOverThis.ArgumentClass
{
private IDontHaveControlOverThis.ArgumentClass arg = new IDontHaveControlOverThis.ArgumentClass();
public String AnyCall() => $"MyArgumentCLass::AnyCall({arg.AnyCall()})";
}
}
public class Program
{
public static void Main()
{
// I don't have control over this
IDontHaveControlOverThis.ServiceClass service = new IDontHaveControlOverThis.ServiceClass();
//This obviously works
IDontHaveControlOverThis.ArgumentClass arg = new IDontHaveControlOverThis.ArgumentClass();
Console.WriteLine($"Result: {service.ServiceCall(arg)}");
// How to make this work?
IDontHaveControlOverThis.ArgumentClass myArg = new MyCode.MyArgumentClass();
Console.WriteLine($"Result: {service.ServiceCall(myArg)}");
}
}
Based on the code sample you show, the answer is you can't. You need to be able to modify the behavior of IDontHaveControlOverThis.ArgumentClass, by setting a property, or creating a new instance with different constructor parameters in order to modify the servicecall. (It now always returns the same string, so the servicecall is always the same)
If you are able to modify the behavior of the ArgumentClass by setting properties.
You could create wrappers for the sealed classes in your own code, and use that throughout your codebase.
public class MyArgumentClass
{
// TODO: Set this to a useful value of ArgumentClass.
internal IDontHaveControlOverThis.ArgumentClass InnerArgumentClass { get; }
public virtual string AnyCall() => "???";
}
public class MyServiceClass
{
private IDontHaveControlOverThis.ServiceClass innerServiceClass
= new IDontHaveControlOverThis.ServiceClass();
public virtual string ServiceCall(MyArgumentClass argument)
{
return innerServiceClass.ServiceCall(argument.InnerArgumentClass);
}
}
or
public class MyArgumentClass
{
public virtual string AnyCall() => "???";
}
public class MyServiceClass
{
private IDontHaveControlOverThis.ServiceClass innerServiceClass
= new IDontHaveControlOverThis.ServiceClass();
public string ServiceCall(MyArgumentClass argument)
{
var serviceArgument = Convert(argument);
return innerServiceClass.ServiceCall(serviceArgument);
}
private IDontHaveControlOverThis.ArgumentClass Convert(MyArgumentClass argument)
{
// TODO: implement.
}
}
The compiler error message
Cannot implicitly convert type 'MyCode.MyArgumentClass' to 'IDontHaveControlOverThis.ArgumentClass'
note: emphasis mine
should give you a hint as to what you can do
public class MyArgumentClass {
private IDontHaveControlOverThis.ArgumentClass arg = new IDontHaveControlOverThis.ArgumentClass();
public String AnyCall() => $"MyArgumentCLass::AnyCall({arg.AnyCall()})";
public static implicit operator IDontHaveControlOverThis.ArgumentClass(MyArgumentClass source) {
return source.arg;
}
}
So now your "wrapper" exposes the 3rd party dependency as needed
IDontHaveControlOverThis.ArgumentClass myArg = new MyCode.MyArgumentClass();
or directly
var myArg = new MyCode.MyArgumentClass();
Console.WriteLine($"Result: {service.ServiceCall(myArg)}");
Reference User-defined conversion operators (C# reference)
Which can allow for abstracting your code
namespace MyCode {
public interface IMyService {
String ServiceCall(MyArgumentClass argument);
}
public class MyServiceClass : IMyService {
public string ServiceCall(MyArgumentClass argument) {
IDontHaveControlOverThis.ServiceClass service = new IDontHaveControlOverThis.ServiceClass();
return service.ServiceCall(argument);
}
}
}
I have 2 classes:
public class Access
{
public class Job
{
public int Id { get; set; }
protected string JobName { get; set; }
}
}
Class2.cs
public class Full: Access.Job
{
}
Full ful = new Full();
Why I'm not able to access the ful.JobName member?
Because You are trying to access protected method from outside the class. Only public methods are available. You can access the property/variably/method that is protected, only in the inherited class, but not from outer code:
public class Full: Access.Job
{
public void mVoid()
{
Console.WriteLine(this.JobName);
}
protected void mProtVoid()
{
Console.WriteLine(this.JobName);
}
private void mPrivateVoid()
{
Console.WriteLine("Hey");
}
}
Full myFull = new Full();
myFull.mVoid(); //will work
myFull.mProtVoid(); //Will not work
myFull.mPrivateVoid(); //Will not work
If You need to get to the protected property, there are 2 ways (3 actually, but Reflection is the dirty way and should be avoided):
1. Make it public
If it will be set to public, it will be stil inherit and You can directly access it:
Full nFull = new Full();
Console.Write(nFull.JobName);
2. Make a "wrapper"/"facade"
Create new property or method, that will just access the hidden property and return it in expected format.
public class Full: Access.Job
{
public string WrappedJobName { get { return this.JobName; } }
public string WrappedJobName => this.JobName; //C# 6.0 syntax
}
Full mFull = new Full();
Console.WriteLine(mFull.WrappedJobName);
I have the following classes, and when I call CreateQuerySettings on the BaseScriptConfigurationList, it returns the new QuerySettings from ConfigurationList, rather than the HierarchicalQuerySettings value in BaseScriptConfigurationList:
public abstract class ConfigurationList<TConfigurationObject, TPropertyEnum>
{
public QuerySettings<TConfigurationObject, TPropertyEnum> CreateQuerySettings()
{
return new QuerySettings<TConfigurationObject, TPropertyEnum>();
}
}
public class BaseScriptConfigurationList : EditableConfigurationList<BaseScriptConfiguration, BaseScriptConfiguration.Property>
{
public BaseScriptConfigurationList(ConfigurationManager configurationManager)
: base(configurationManager, InternalAdminObjectType.BaseScript)
{
_BaseScriptPageListWatcher = new ConfigurationList<BaseScriptPageConfiguration, BaseScriptPageConfiguration.Property>.
ConfigurationWatcher(null);
_ConfigurationWatcher.ChildWatchers.Add(_BaseScriptPageListWatcher);
}
public new QuerySettings<BaseScriptConfiguration, BaseScriptConfiguration.Property> CreateQuerySettings()
{
return new HierarchicalQuerySettings<BaseScriptConfiguration, BaseScriptConfiguration.Property, BaseScriptQueryChildrenSettings>();
}
}
Edit: I make the call from another class where TConfigurationObjectList is BaseScriptConfigurationList. I've added the constructor to the code above so you can see what it's doing. Please note that EditableConfigurationList inherits from ConfigurationList.
TConfigurationObjectList cl = (TConfigurationObjectList)typeof(TConfigurationObjectList).GetConstructor(new Type[] { typeof(ConfigurationManager) }).Invoke(new object[] { Manager.ConfigurationManager });
var querySettings = cl.CreateQuerySettings();
When I make this call, it goes into the ConfigurationList.CreateQuerySettings method.
How can I hide the CreateQuerySettings method, so that when I call it from the BaseScriptConfigurationList class, I get a HierarchicalQuerySettings object?
The new modifier can be beasty. Note that you are hiding and not overriding in your example. You are not showing that part of the code, but I assume you have this situation:
class Base
{
public static void BaseMethod() { Console.WriteLine("BASE!"); }
}
class Derived : Base
{
// Hides Base.BaseMethod()
new public static void BaseMethod() { Console.WriteLine("DERIVED!"); }
}
Base a = new Base();
a.BaseMethod(); // -> "BASE!"
Base b = new Derived();
b.BaseMethod(); // -> "BASE!"
Derived b = new Derived();
b.BaseMethod(); // -> "DERIVED!"
In BaseScriptConfigurationList.CreateQuerySettings()
you're return type is QuerySettings<T,T> so you will always get that type as a return value, but you are returning a HierarchicalQuerySettings. You can one, change the return type of CreateQuerySettings() to HierarchicalQuerySettings or two, cast the object to its child type "HierarchicalQuerySettings". If you really want to hide it, you can do this:
public class newclass : BaseScriptConfigurationList
{
public new HierarchicalQuerySettings<BaseScriptConfiguration, BaseScriptConfiguration.Property> CreateQuerySettings()
{
return (HierarchicalQuerySettings<BaseScriptConfiguration, BaseScriptConfiguration.Property>)base.CreateQuerySettings();
}
}
But that doesn't really seem efficient and i advise against it. Like i said, i maybe missing some other requirement, but based on the info that you gave..
Basically, what I'm seeing (and making assumptions) that TConfigurationObjectList Inhertis from ConfigurationList somewhere along the lines, so on and so forth, all the way up to EditableConfigurationList. since you are dynamically creating an instance of the class TConfigurationObjectList, and calling the method from that point, you will be calling the base ConfigurationList member CreateQuerySettings. You do not have access to the new CreateQuerySettings. If you are creating the class BaseScriptConfigurationList instance at this point, cast the object ((BaseScriptConfigurationList)cl).CreateQuerySettings(). That being said. if you do not know what you have at runtime:
var obj = typeof(TConfigurationObjectList).GetConstructor(new Type[] { typeof(ConfigurationManager) }).Invoke(new object[] { Manager.ConfigurationManager });
var cl = (obj as BaseScriptConfigurationList) ?? (TConfigurationObjectList)obj;
// or do something else
var querySettings = cl.CreateQuerySettings();
Note i am assuming your architecture is roughly set up like this:
public abstract class ConfigurationList<TConfigurationObject, TPropertyEnum>
{
public QuerySettings<TConfigurationObject, TPropertyEnum> CreateQuerySettings()
{
return new QuerySettings<TConfigurationObject, TPropertyEnum>();
}
}
public class TConfigurationObjectList : ConfigurationList<BaseScriptConfiguration, BaseScriptConfiguration.Property>
{
}
public class EditableConfigurationList<T, T1> : TConfigurationObjectList
{
protected EditableConfigurationList(ConfigurationManager configurationManager, object baseScript)
{
throw new NotImplementedException();
}
}
public class BaseScriptConfigurationList : EditableConfigurationList<BaseScriptConfiguration, BaseScriptConfiguration.Property>
{
public BaseScriptConfigurationList(ConfigurationManager configurationManager)
: base(configurationManager, InternalAdminObjectType.BaseScript)
{
}
public new QuerySettings<BaseScriptConfiguration, BaseScriptConfiguration.Property> CreateQuerySettings()
{
return new HierarchicalQuerySettings<BaseScriptConfiguration, BaseScriptConfiguration.Property, BaseScriptQueryChildrenSettings>();
}
}
public class QuerySettings<T, T1>
{
}
public class HierarchicalQuerySettings<T, T1, T2> : QuerySettings<BaseScriptConfiguration, BaseScriptConfiguration.Property>
{
}
public class BaseScriptQueryChildrenSettings
{
}
public class BaseScriptPageConfiguration
{
public class Property
{
}
}
public class InternalAdminObjectType
{
public static object BaseScript { get; set; }
}
public class ConfigurationManager
{
}
public class BaseScriptConfiguration
{
public class Property
{
}
}
Create a base interface for the ConfigurationList class (say IConfigurationList) and use this interface as the data type for the variable cl instead of TConfigurationList.
Can we make a property of a class visible to public , but can only be modified by some specific classes?
for example,
// this is the property holder
public class Child
{
public bool IsBeaten { get; set;}
}
// this is the modifier which can set the property of Child instance
public class Father
{
public void BeatChild(Child c)
{
c.IsBeaten = true; // should be no exception
}
}
// this is the observer which can get the property but cannot set.
public class Cat
{
// I want this method always return false.
public bool TryBeatChild(Child c)
{
try
{
c.IsBeaten = true;
return true;
}
catch (Exception)
{
return false;
}
}
// shoud be ok
public void WatchChild(Child c)
{
if( c.IsBeaten )
{
this.Laugh();
}
}
private void Laugh(){}
}
Child is a data class,
Parent is a class that can modify data,
Cat is a class that can only read data.
Is there any way to implement such access control using Property in C#?
Rather than exposing the inner state of the Child class you could provide a method instead:
class Child {
public bool IsBeaten { get; private set; }
public void Beat(Father beater) {
IsBeaten = true;
}
}
class Father {
public void BeatChild(Child child) {
child.Beat(this);
}
}
Then the cat can't beat your child:
class Cat {
public void BeatChild(Child child) {
child.Beat(this); // Does not compile!
}
}
If other people need to be able to beat the child, define an interface they can implement:
interface IChildBeater { }
Then have them implement it:
class Child {
public bool IsBeaten { get; private set; }
public void Beat(IChildBeater beater) {
IsBeaten = true;
}
}
class Mother : IChildBeater { ... }
class Father : IChildBeater { ... }
class BullyFromDownTheStreet : IChildBeater { ... }
This is usually achieved by using separate assemblies and the InternalsVisibleToAttribute. When you mark the set with internal classes within the current assembly will have access to it. By using that attribute, you can give specific other assemblies access to it. Remember by using Reflection it will still always be editable.
I have a class that requests that when called a string is sent when requesting / initializing it.
class Checks
{
public Checks(string hostname2)
{
// logic here when class loads
}
public void Testing()
{
MessageBox.Show(hostname2);
}
}
How would it be possible to take the string "hostname2") in the class constructor and allow this string to be called anywhere in the "Checks" class?
E.g. I call Checks(hostname2) from the Form1 class, now when the Checks class is initialized I can then use the hostname2 string in my Checks class as well
Declare a member inside the class and assign the value you passed to the member inside the constructor:
class Checks
{
private string hostname2;
public Checks(string hostname2)
{
this.hostname2 = hostname2; // assign to member
}
public void Testing()
{
MessageBox.Show(hostname2);
}
}
If you also need to have outside access, make it a property:
class Checks
{
public string Hostname2 { get; set; }
public Checks(string hostname2)
{
this.Hostname2 = hostname2; // assign to property
}
public void Testing()
{
MessageBox.Show(Hostname2);
}
}
Properties start with a capital letter by convention. Now you can access it like this:
Checks c = new Checks("hello");
string h = c.Hostname2; // h = "hello"
Thanks to Andy for pointing this out: if you want the property to be read-only, make the setter private:
public string Hostname2 { get; private set; }
You need to copy the constructor argument in a class variable:
class Checks {
// this string, declared in the class body but outside
// methods, is a class variable, and can be accessed by
// any class method.
string _hostname2;
public Checks(string hostname2) {
_hostname2 = hostname2;
}
public void Testing() {
MessageBox.Show(_hostname2);
}
}
You can expose a public property to retun the hostname2 value which is the standard for exposing your private varibles
class Checks
{
private string _hostname;
public Checks(string hostname2)
{
_hostname = hostname2;
}
public string Hostname
{
get { return _hostname; }
}
}