Changing class attributes outside class - c#

I have a public class
public class Interview
{
public int InterviewId;
public string ApplicantName;
...
public List<AnsweredQuestions> AnsweredQuestions;
public Questionnaire questionnaire;
}
and use it in a main program like this:
Interview interview = new Interview();
interview.InterviewId = 1;
and a Questionnaire class
public class Questionnaire
{
public int questionnaireId;
public string outputFile;
...
}
How can I prevent modifying the attribute int the main program:
interview.questionnaire.outputFile
I found I was able to use the DocumentManager class in the main program like this:
interview = documentManager.GetInterviewSession();
interview.questionnaire = documentManager.GetQuestionnaireManagement();
interview.AnsweredQuestions = documentManager.GetInterviewAnsweredQuestions();
by using this
public class DocumentManager
{
private readonly Interview _interview;
...
public DocumentManager(Interview interview)
{
_interview = interview;
}
I'm sure I should be encapsulating, but I'm not sure how. Any help would be appreciated.
Thanks!

I'm not sure I entirely get the question, but this is the usual method for read-only encapsulation:
public class Questionnaire
{
public string OutputFile { get; private set; }
}
This creates a property named OutputFile that can be read publically, but only written by the Questionnaire class.
Alternatively, you may want to use protected set; if you want classes deriving from Questionnaire to be able to set OutputFile.

If you need certain properties to be immutable then you can supply those properties in the constructor of the class.
Also instead of using fields, you can use properties that allow you to dictate whether the property getter and setter are private/public/internal/protected.
In your sample, you could have InterviewId as a property with a public get accessor and a private only set accessor. This means that only the class itself can set the interviewId. If the only way to set the interviewId is at the constructor of the class, then there is no way for the consuming code to change it (other than by using reflection of course)
public class Questionnaire
{
public Questionnaire(int questionnaireId, string outputFile)
{
QuestionnaireId = questionnaireId;
OutputFile = outputFile
}
public int QuestionnaireId {get; private set;}
public string OutputFile { get; private set; }
...
}

Related

What difference does this `private set` make within this immutable class

I'm studying this simple class and wondering what difference the private set of the Name property actually makes?
If that line simply read public string Name { get; } how would the user's interaction with the class change?
public class Contact2
{
// Read-only properties.
public string Name { get; private set; }
public string Address { get; }
// Private constructor.
private Contact2(string contactName, string contactAddress)
{
Name = contactName;
Address = contactAddress;
}
// Public factory method.
public static Contact2 CreateContact(string name, string address)
{
return new Contact2(name, address);
}
}
They are both read-only properties, and objects of this class can only be constructed via the static method, so does it matter if the set of name is private or not?
EDIT
It is part of this MSDN code:
https://msdn.microsoft.com/en-us/library/bb383979.aspx
In C# 6:
public string Name { get; private set; }
Can be set from any method within the class.
public string Address { get; }
Is a read-only property and can only (and must) be set on initialization.
In your code they're functioning the same way, however the read-only property enforces an additional constraint making the property immutable as it can only be set once, whereas you could add a method to the class which mutates Name making the class mutable.
Getter-only auto properties like public string Name { get; } were not allowed before C# 6.0, so the code would not compile. That's why you needed a private setter before.
See: Getter-only auto-properties.

Prevent instantiation of MongoDB data model outside of current assembly or prevent misuse

Ive got a mongo database set up and if its designed to use strongly typed objects:
public class Message : IDatabaseObject
{
[DataMember]
[BsonId]
[BsonRepresentation(BsonType.ObjectId)]
public string Id { get; set; }
[DataMember]
public string MessageBody { get; set; }
}
The class and all properties need to be public for MongoDB to use it as an object
I was about to make a factory to create a new instance as opposed to creating an instance of Message (duplicating code) each time but then I realised there would be more than one way to create a Message.
Is there a way to prevent direct instantiation of the data object outside of the assembly?
You can't make a private or internal property for serialization in mongo, but you can make the setter of property private or internal (mongo c# driver will take care of private setters for serializing and deserializing).
Make the constructor and setters internal or private (based on your use-case)
public class Message
{
[DataMember]
[BsonId]
[BsonRepresentation(BsonType.ObjectId)]
public string Id { get; internal set; }
[DataMember]
public string MessageBody { get; internal set; }
internal Message() { }
}
public static class MessageFactory
{
public static Message Create()
{
return new Message();
}
}
You can expose a public factory method like DatabaseObjectFactory.Create<Message>() or Message.Create(), while keeping the constructor internal or even private.
If it is enough that during compile time you can't instanciate the class, Fody might be what you want. Specificially Publicize.Fody.
It allows you to write your class as internal. Compile it. Then have it run as a public class.

How to access private variables using { get; set; }

I'd like to create a class for my website with a lot of private variable.
I thought there was a solution not to write all the getters and setters for each variable, something like
private int confirmed { get; set; }
Is it the right way? ANd then, how do I access this value from outside the class?
I've tried .confirmed , I get the error saying that it's private (which I understand)
But more surprising, .getConfirmed() or getconfirmed() do not work either.
I thought that the { get; set; } would create implicitely those methods.
Can someone clarify this concern for me please?
You can declare your property as public, then mark the getter or setter individually as private:
public int confirmed { get; private set; }
That way, you can access confirmed outside of your defined class:
Console.WriteLine(myClass.confirmed); // This is OK
myClass.confirmed = "Nothing"; // Can't do this
And the only one who can set the value of confirmed is then MyClass:
public class MyClass {
public int confirmed { get; private set; }
public MyClass() {
this.confirmed = "This"; // This is fine as we have private access
}
}
You need to understand that,
private int confirmed { get; set; }
will be expanded to a set of private methods with a private backing field,
private int _confirmed;
private int confirmed_get()
{
return this._confirmed;
}
private void confirmed_set(int value)
{
this._confirmed = value;
}
Thus, marking the property private makes both the accessor and the mutator also private, which is why you cannot access them outside of the class. Also, these methods are not accessible at compile time, so calling instance.confirmed_get() is not permitted, only instance.confimed both to read and write to the property.
What you might want is to declare it public,
public int confirmed { get; set; }
where the behavior is similar (the field still is private), but both method are now public. As others have mention you can individually modify the get and set for readonly or writeonly type of behavior,
public int confirmed { get; private/protected set; }
or
public int confirmed { private/protected get; set; }
And one last thing, you should get into the habit of using camel case for propeties, e.g. Confirmed and lower camel case for fields, e.g. confirmed (some might even do _confirmed). It is a popular naming conventions to distinguish the two types, especially for consumers of the class.
how do I access this value from outside the class?
You can't (without reflection form trusted code). They're private. If you want the getter to be public but the setter private then do
public int confirmed { get; private set; }
I thought that the {get;set;} would create implicitly those methods.
It does, but they're not accessible at design time.
Just do this if you want to get it from outside the class.
public int confirmed { get; set; }
or you can go this route:
private int confirmed;
public int Confirmed
{
get { return confirmed }
set { confirmed = value; }
}
There are multiple ways to perform such action. Depending upon your requirements, you can choose any one method from below:
// Old Conventional - Statement body
public class SampleClass1
{
public bool CanAccessFromOutside
{
get { return _cannotAccessFromOutside; }
}
private bool _cannotAccessFromOutside;
private void DoSomething()
{
_cannotAccessFromOutside = true;
}
}
// Expression Bodied Property
public class SampleClass2
{
public bool CanAccessFromOutside => _cannotAccessFromOutside;
private bool _cannotAccessFromOutside;
private void DoSomething()
{
_cannotAccessFromOutside = true;
}
}
// Auto Property
public class SampleClass3
{
public bool CanAccessFromOutside { get; private set; }
private void DoSomething()
{
CanAccessedFromOutside = true;
}
}

Exposing enum type defined in a base library

I am trying to revise my logging library. Here is where I'm stuck. I use an enumeration, let's call it ActionType, to identify my operations like UserLogin, PurchaseOrder... hundreds of them. And I use this type in my logger methods. But since I am seperating my logger library from my project specific code in the sake of loose coupling and base library can't access ActionType defined in a project, how can I achieve this. To clarify it let me explain same case in java. Java allows enums to implement interfaces. So I could write:
In base logger library I could define;
public interface IActionType {}
and in one of my several projects
public enum ActionType implements IActionType {UserLogin, PurchaseOrder, .....}
So when I called my logger.log(ActionType.UserLogin, ....) base library would get the underlying action. This would all be suffice. Is there anyway around it to accomplish this in c#? By the way, I considered using IoC containers, but I want something more elegant.
Many thanks for any help...
Here is approach log4net uses for Level class (yes, it is class, not enum):
public class ActionType : IActionType
{
public static readonly ActionType UserLogin;
public static readonly ActionType PurchaseOrder;
static ActionType()
{
UserLogin = new ActionType(1, "User Login");
// ...
}
public ActionType(int value, string name)
{
// verify arguments values
Value = value;
Name = name;
}
public int Value { get; private set; }
public string Name { get; private set; }
}
And interface
public interface IActionType
{
int Value { get; }
string Name { get; }
}
Usage:
logger.Log(ActionType.UserLogin);
Lazy beat me to it but I'll post my solution anyway
public void MyUsage(ITypesafeEnum myEnum)
{
Console.WriteLine(myEnum.Name);
Console.WriteLine(myEnum.Val);
}
public interface ITypesafeEnum{
string Name{get;}
int Val {get;}
}
public class TypesafeEnum:ITypesafeEnum{
public string Name {get;private set;}
public int Val {get;private set;}
private TypesafeEnum(){}
private TypesafeEnum(string name, int val){
Name = name;
Val = val;
}
public static readonly TypesafeEnum Bedroom = new TypesafeEnum("Bedroom", 1);
public static readonly TypesafeEnum LivingRoom = new TypesafeEnum("Living Room",2);
}
Here is another approach that uses generics:
public void Log<EnumType>(EnumType enumMember)
{
var name = enumMember.ToString();
int value = (int)(object)enumMember;
Console.WriteLine(name + " = " + value);
}
Calling the above method like this:
Log<ActionType>(ActionType.UserLogin);
Log<ActionType>(ActionType.PurchaseOrder);
Results in an output like the following:
UserLogin = 0
PurchaseOrder = 1

XmlSerializer with parameterless constructor with no public properties or fields... Is it possible?

Having the following class (.Net 3.5):
public class Something
{
public string Text {get; private set;}
private Something()
{
Text = string.Empty;
}
public Something(string text)
{
Text = text;
}
}
This serializes without error but the resulting XML does not include the Text property since it does not have a public setter.
Is there a way (the simpler, the better) to have the XmlSerializer include those properties?
XmlSerializer only cares about public read/write members. One option is to implement IXmlSerializable, but that is a lot of work. A more practical option (if available and suitable) may be to use DataContractSerializer:
[DataContract]
public class Something
{
[DataMember]
public string Text {get; private set;}
private Something()
{
Text = string.Empty;
}
public Something(string text)
{
Text = text;
}
}
This works on both public and private members, but the xml produced is not quite the same, and you can't specify xml attributes.
No. XML Serialization will only serialized public read/write fields and properties of objects.
Try
[Serializable]
public class Something
{
...
}

Categories