How to access protected member in an inherited class - c#

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

Related

C# restricting use of a class

The below code does what I would like it to do. The code in the Main method looks and behaves exactly as desired. However, it would be preferable if the class UserMenu, Home and DropdownMenu2 could only be used by the HeaderNavigationMenu to protect other developers from trying to used them outside of the HeaderNavigationMenu class. Additionally most articles frown upon making everything public.
Question:
Is the design patter being used below appropriate or is there something better and more acceptable to use in this scenario?
Edit: The reason for this design.
I wanted the end user of HeaderNavigationMenu to just be able to use the dot notation to get a list of available options. This Architecture accomplishes this goal (ex: navigationMenu.DropdownMenu2.SelectOption3())
Wanted anyone else who eventually might need to edit the code to understand that the classes UserMenu, Home and DropDownMenu2 where very specifically designed to be implemented by HeaderNavigationMenu class.
public class HeaderNavigationMenu
{
public HeaderNavigationMenu()
{
UsersMenu = new UsersMenu();
Home = new Home();
DropdownMenu2 = new DropdownMenu2();
}
public UsersMenu UsersMenu { get; set; }
public Home Home { get; set; }
public DropdownMenu2 DropdownMenu2 { get; set; }
}
public class UsersMenu
{
...
}
public class Home
{
...
}
public class DropdownMenu2
{
public void SelectOption3()
{
...
}
...
}
static void Main(string[] args)
{
HeaderNavigationMenu navigationMenu = new HeaderNavigationMenu();
navigationMenu.DropdownMenu2.SelectOption3();
// The following code is an example of undesired capability;
// prefer if Home class could only be
// used by HeaderNavigationMenu class
Home home = new Home();
}
Restrict access to the class constructors. If they are declared as "internal" then the classes may only be created by your code.
If you're looking to protect against the instantiation of UsersMenu, DropdownMenu2, and Home from outside HeaderNavigationMenu but still within the same project as HeaderNavigationMenu then there is a neat trick that can achieve this behavior. You can use public nested classes with private constructors which statically initialize their own factory methods. The basic template for this would be:
public class Outer{
private static Func<Inner> _innerFactory;
public Inner ExposedInner {get; private set;}
public Outer(){
// Force the static initializer to run.
System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(typeof(Inner).TypeHandle);
// Call the newly created factory method instead of a regular constructor.
ExposedInner = _innerFactory();
}
public class Inner {
static Inner(){
// Initialize Outer's static factory method.
_innerFactory = () => new Inner();
}
// Inner cannot be instantiated (without reflection) because its constructor is private.
private Inner(){}
// This method is now exposed for anyone to use.
public void DoStuff(){ Console.WriteLine("Did stuff"); }
}
}
Here's this concept implemented in your example:
class Program
{
static void Main(string[] args)
{
HeaderNavigationMenu navigationMenu = new HeaderNavigationMenu();
navigationMenu.DropdownMenu2.SelectOption3();
// This line will no longer work because the constructors
// for the inner classes are private.
HeaderNavigationMenu.HomeImpl home = new HeaderNavigationMenu.HomeImpl();
Console.ReadKey();
}
}
public class HeaderNavigationMenu
{
//Private factory methods that are statically initialized
private static Func<UsersMenuImpl> _createUsers;
private static Func<DropdownMenu2Impl> _createDropdown;
private static Func<HomeImpl> _createHome;
public HeaderNavigationMenu()
{
//Force the static constructors to run
System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(typeof(UsersMenuImpl).TypeHandle);
System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(typeof(HomeImpl).TypeHandle);
System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(typeof(DropdownMenu2Impl).TypeHandle);
UsersMenu = _createUsers();
Home = _createHome();
DropdownMenu2 = _createDropdown();
}
public UsersMenuImpl UsersMenu { get; set; }
public HomeImpl Home { get; set; }
public DropdownMenu2Impl DropdownMenu2 { get; set; }
public class UsersMenuImpl
{
//Static constructor to make the class factory method
static UsersMenuImpl()
{
_createUsers = () => new UsersMenuImpl();
}
private UsersMenuImpl() { }
}
public class HomeImpl
{
//Static constructor to make the class factory method
static HomeImpl()
{
_createHome = () => new HomeImpl();
}
private HomeImpl() { }
}
public class DropdownMenu2Impl
{
//Static constructor to make the class factory method
static DropdownMenu2Impl()
{
_createDropdown = () => new DropdownMenu2Impl();
}
private DropdownMenu2Impl() { }
public void SelectOption3()
{
}
}
}
With this, you will still be able to use all the public properties of the inner classes however no one will be able to instantiate the inner classes from outside HeaderNavigationMenu and only HeaderNavigationMenu has access to the factory methods.
I don't really understand what your use case is and I've never coded like this but one way of only exposing the required behaviour of HeaderNavigationMenu would be to make the classes internal and the variables private and then expose only the SelectOption3() method, as below.
If you uncomment the line
//Home home = new Home();
you will get a compiler error.
class Program
{
static void Main(string[] args)
{
HeaderNavigationMenu navigationMenu = new HeaderNavigationMenu();
navigationMenu.DropdownMenu2SelectOption3();
// The following code is an example of undesired capability;
// prefer if Home class could only be
// used by HeaderNavigationMenu class
//Home home = new Home();
}
}
public class HeaderNavigationMenu
{
UsersMenu usersMenu;
Home home;
DropdownMenu2 dropdownMenu2;
public HeaderNavigationMenu()
{
usersMenu = new UsersMenu();
home = new Home();
dropdownMenu2 = new DropdownMenu2();
}
public void DropdownMenu2SelectOption3()
{
dropdownMenu2.SelectOption3();
}
class UsersMenu
{
}
class Home
{
}
class DropdownMenu2
{
public void SelectOption3()
{
}
}
}
You could make UsersMenu, Home, and DropdownMenu2 public abstract classes. Then have private classes nested inside of HeaderNavigationMenu which extend the public abstract versions.
public abstract class UsersMenu
{
}
public abstract class Home
{
}
public abstract class DropdownMenu2
{
public void SelectOption3()
{
// Code for SelectOption3...
}
}
public class HeaderNavigationMenu
{
public HeaderNavigationMenu()
{
UsersMenu = new UsersMenuImpl();
Home = new HomeImpl();
DropdownMenu2 = new DropdownMenu2Impl();
}
public UsersMenu UsersMenu { get; }
public Home Home { get; }
public DropdownMenu2 DropdownMenu2 { get; }
private class UsersMenuImpl : UsersMenu
{
}
private class HomeImpl : Home
{
}
private class DropdownMenu2Impl : DropdownMenu2
{
}
}
Fellow developers can see and use the UsersMenu, Home, and DropdownMenu2 abstract classes, but cannot create instances of them. Only HeaderNavigationMenu can.
Of course, another developer could always create their own classes deriving from the public abstract ones, but there is only so much you can do. UsersMenu, Home, and DropdownMenu2 have to be public in order to be public properties.

accessing the list declared in a class from another class

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

how to implement selective property-visibility in c#?

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.

Using strings from other classes C#

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

Tableadapters Not Marked as serializable?

I have 2 tables in a database and then using a datamodel in visual studio (datasets), then using 2 classes to store methods and properties of these 2 tables.
I want to store information gathered from a webform into a list but for some reason when trying to add the list to a stateview I get this error:
Type '"".""TableAdapters.""TableAdapter' in Assembly '"", Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' is not marked as serializable.
I have already marked the class as serializable but now the tableadapters? Here is my code:
[System.ComponentModel.DataObject]
[Serializable]
public class Example
{
int _example1 = new int();
string _example2;
string _example3;
decimal _example4 = new decimal();
public int example1
{
get { return _example1; }
set { _example1 = value; }
}
public string example2
{
get { return _example2; }
set { _example2 = value; }
}
public string example3
{
get { return _example3; }
set { _example3 = value; }
}
public decimal example4
{
get { return _example4; }
set { _example4 = value; }
}
private tblTestTableAdapter _testAdapter = null;
protected tblTestTableAdapter Adapter
{
get
{
if (_testAdapter == null)
_testAdapter = new tblTestTableAdapter();
return _testAdapter;
}
}
Webform:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
}
else
{
example = (List<Example>)ViewState["Examples"];
}
}
private List<Example> example;
public List<Example> GetExample()
{
return example;
}
protected void btnRow_Click(object sender, EventArgs e)
{
example = new List<Example>();
Example e = new Example();
e.example1 = Convert.ToInt32(txtE1.Text);
c.example2 = txtE2.Text;
c.example3 = txtE3.Text;
c.example4 = Convert.ToDecimal(txtE4.Text);
example.Add(e);
ViewState["Examples"] = example;
btnRow.Enabled = false;
}
What is the problem?
When marking a class as Serializable every class and dependent object class within it that is exposed externally must all be marked as Serializable. That's because whatever process that is going to perform the serialization will attempt to serialize every public element properly.
FYI, tableadapters are not meant to be exposed publicly because they expose functionality rather than properties and fields. Functionality is not transferred across the serial connection. I would recommend you remove the public nature of the adapter in your example.
Edit 2:
After rereading your code and looking for the documentation for the protection levels of serialized properties, I ran into this link that describes the real problem here. You can't serialize a readonly property (I totally forgot about this), and your tableadapter is property is readonly. Provide it with a set, and it should begin functioning.
Edit: Code sample
[Serializable]
public class MySerializableClass
{
public MySerializableClass()
{
}
// This string serializes ok
public string MyStringProperty { get; set; }
// Because this property is public in scope it must be serializable
// because it will be translated at a public scope. This will throw
// an exception
public myNonSerializableClass NotSerializableObject { get; set; }
// Because this property is private in scope, it will not be included
// in any serialization calls, so it will not throw an exception, but
// it will also not be available in whatever remote class calls it.
private myNonSerializableClass SerializableObject { get; set; }
// Because this property object is serializable in code it will be
// ok to make it public because it will natively serialize itself
public MyOtherSerializableClass OtherSerializableObject { get; set; }
}

Categories