I have a read-only object but somewhere it's properties getting updated. Does C# have anything to restrict that too from direct changes as well as via reflection?
Here is the POC code
class Program
{
static void Main(string[] args)
{
ReadOnlyCreator tester = new ReadOnlyCreator();
tester.ModifyTester();
Console.ReadLine();
}
}
class ClassUnderTest
{
public string SomeProp { get; set; }
}
class ReadOnlyCreator
{
private readonly ClassUnderTest _classUnderTest;
public ReadOnlyCreator()
{
_classUnderTest = new ClassUnderTest { SomeProp = "Init" };
}
public void ModifyTester()
{
Console.WriteLine("Before: " + _classUnderTest.SomeProp);
var modifier = new Modifier(_classUnderTest);
modifier.Modify();
Console.WriteLine("After: " + _classUnderTest.SomeProp);
}
}
class Modifier
{
private ClassUnderTest _classUnderTest;
public Modifier(ClassUnderTest classUnderTest)
{
_classUnderTest = classUnderTest;
}
public void Modify()
{
_classUnderTest.SomeProp = "Modified";
}
If you want a read only object you should make it read only. i.e.
class ClassUnderTest
{
public string SomeProp { get; }
public ClassUnderTest(string someProp) => SomeProp = someProp;
}
You could also use init only setters if you are using c#9. This allow the property to be set only during construction of the object:
class ClassUnderTest
{
public string SomeProp { get; init; }
}
If you are using value types you can (and should) declare the whole type as readonly. See also Choosing Between Class and Struct
public readonly struct StructUnderTest
This does not protect against reflection or unsafe code. Using these features is deliberately circumventing the rules, so it is up to the developer to ensure it is safe.
Related
I want to use textBox1.Text in a different class not just in the main where the text boxes are defined so to say. Is there any way to make it global? Because it only allows me to use it in the main thing, not in the seperate class that I have to make in my task.
I need to store the text from the textBox in a List that is in a different class so the user can't add the same name twice so I need to remember what was typed in in the first input.
This is the class where I created a List and where I want to store those inputs:
internal class Clanovi
{
public static List<Clan> Dodaj()
{
List<Clan> clanovi = new List<Clan>();
clanovi.Add(new Clan() { KorIme = textBox1.Text, Lozinka = textBox2.Text });
return clanovi;
}
}
class Clan
{
public string KorIme { get; set; }
public string Lozinka { get; set; }
}
This is WinForm btw.
Your variable names are in another language so it is hard to understand but I think you want this
internal class Clanovi
{
public static List<Clan> Dodaj()
{
Global.clanovi.Add(new Clan() { KorIme = textBox1.Text, Lozinka = textBox2.Text });
// you don't need to return this since it is already global
return clanovi;
}
}
public static class Global
{
public static List<Clan> clanovi = new List<Clan>();
}
public static class Clan
{
public static string KorIme { get; set; }
public static string Lozinka { get; set; }
}
Whenever you want to access your global variables, you use the Global class with the static items in it.
i suggest to:
change the modifiers property in the properties of the textbox to public.
write this code in the other class :
Form_name/class_name myTextbox = new form_name/class_name();
ex:
Form1 myTextbox = new Form1();
now u can use in any other class/form: mytextbox.Textbox.text.
internal class Clanovi
{
Clan myTextbox = new Clan();
public static List<Clan> Dodaj()
{
List<Clan> clanovi = new List<Clan>();
clanovi.Add(new Clan() { KorIme = myTextbox.textBox1.Text, Lozinka = textBox2.Text });
return clanovi;
}
}
I would like to create a generic method that can convert an object to a different type. I could not find any solutions for this scenario. Is this possible in C#?
class A
{
public string Name { get; set; }
}
class A1: A
{
public string ConnectionString { get; set; }
}
class B
{
public string DBName { get; set; }
public string DBConnectionString { get; set; }
}
void Main()
{
A obj = //data
var res = APIToBackEndModel<A, B>(obj);
//Do something
A1 obj1 = //data
var res1 = APIToBackEndModel<A1, B>(obj1);
}
private TResult APIToBackEndModel<T, TResult>(T objTo)
{
(TResult)DBName = (T)objTo.Name;
//OR
var obj = new TResult
{
DBName = (T)objTo.Name
}
}
This did not help me.
You won't be able to do it completely generic, as you rely on certain properties to exist. But you knowing these properties exist, is not enough. You have to guarantee the compiler, they exist. You can do this with Constraints on type parameters. With their help, you can define, that the generic types you use, will have certain properties (for instance implement an interface or inherit from a class).
interface InterfaceIn {
string p1 {get;set;}
void m1();
}
interface InterfaceOut {
string p2 {get;set;}
void m2();
}
class ConcreteIn : InterfaceIn {
public string p1 {get;set;}
public void m1() {}
}
class ConcreteOut1 : InterfaceOut {
public string p2 {get;set;}
public void m2() {}
}
class ConcreteOut2 : InterfaceOut {
public string p2 {get;set;}
public void m2() {}
}
class Program
{
static void Main(string[] args)
{
var a = new ConcreteIn{p1 = "some value"};
var b = mapIt<ConcreteIn, ConcreteOut1>(a);
var c = mapIt<ConcreteIn, ConcreteOut2>(a);
}
public static V mapIt<U, V>(U val) where U: InterfaceIn where V: InterfaceOut, new() {
var res = new V {p2 = val.p1};
return res;
}
}
Depending on how much properties and combinations you have, this may be enough. Or you may be better off with something like Automapper as Hans Kesting suggested. Or, if you can't group together some mappings, you will have to implement every mapping yourself.
I have two C# classes that have many of the same properties (by name and type). I want to be able to copy all non-null values from an instance of Defect into an instance of DefectViewModel. I was hoping to do it with reflection, using GetType().GetProperties(). I tried the following:
var defect = new Defect();
var defectViewModel = new DefectViewModel();
PropertyInfo[] defectProperties = defect.GetType().GetProperties();
IEnumerable<string> viewModelPropertyNames =
defectViewModel.GetType().GetProperties().Select(property => property.Name);
IEnumerable<PropertyInfo> propertiesToCopy =
defectProperties.Where(defectProperty =>
viewModelPropertyNames.Contains(defectProperty.Name)
);
foreach (PropertyInfo defectProperty in propertiesToCopy)
{
var defectValue = defectProperty.GetValue(defect, null) as string;
if (null == defectValue)
{
continue;
}
// "System.Reflection.TargetException: Object does not match target type":
defectProperty.SetValue(viewModel, defectValue, null);
}
What would be the best way to do this? Should I maintain separate lists of Defect properties and DefectViewModel properties so that I can do viewModelProperty.SetValue(viewModel, defectValue, null)?
Edit: thanks to both Jordão's and Dave's answers, I chose AutoMapper. DefectViewModel is in a WPF application, so I added the following App constructor:
public App()
{
Mapper.CreateMap<Defect, DefectViewModel>()
.ForMember("PropertyOnlyInViewModel", options => options.Ignore())
.ForMember("AnotherPropertyOnlyInViewModel", options => options.Ignore())
.ForAllMembers(memberConfigExpr =>
memberConfigExpr.Condition(resContext =>
resContext.SourceType.Equals(typeof(string)) &&
!resContext.IsSourceValueNull
)
);
}
Then, instead of all that PropertyInfo business, I just have the following line:
var defect = new Defect();
var defectViewModel = new DefectViewModel();
Mapper.Map<Defect, DefectViewModel>(defect, defectViewModel);
Take a look at AutoMapper.
There are frameworks for this, the one I know of is Automapper:
http://automapper.codeplex.com/
http://www.lostechies.com/blogs/jimmy_bogard/archive/2009/01/22/automapper-the-object-object-mapper.aspx
Replace your erroneous line with this:
PropertyInfo targetProperty = defectViewModel.GetType().GetProperty(defectProperty.Name);
targetProperty.SetValue(viewModel, defectValue, null);
Your posted code is attempting to set a Defect-tied property on a DefectViewModel object.
In terms of organizing the code, if you don't want an external library like AutoMapper, you can use a mixin-like scheme to separate the code out like this:
class Program {
static void Main(string[] args) {
var d = new Defect() { Category = "bug", Status = "open" };
var m = new DefectViewModel();
m.CopyPropertiesFrom(d);
Console.WriteLine("{0}, {1}", m.Category, m.Status);
}
}
// compositions
class Defect : MPropertyGettable {
public string Category { get; set; }
public string Status { get; set; }
// ...
}
class DefectViewModel : MPropertySettable {
public string Category { get; set; }
public string Status { get; set; }
// ...
}
// quasi-mixins
public interface MPropertyEnumerable { }
public static class PropertyEnumerable {
public static IEnumerable<string> GetProperties(this MPropertyEnumerable self) {
return self.GetType().GetProperties().Select(property => property.Name);
}
}
public interface MPropertyGettable : MPropertyEnumerable { }
public static class PropertyGettable {
public static object GetValue(this MPropertyGettable self, string name) {
return self.GetType().GetProperty(name).GetValue(self, null);
}
}
public interface MPropertySettable : MPropertyEnumerable { }
public static class PropertySettable {
public static void SetValue<T>(this MPropertySettable self, string name, T value) {
self.GetType().GetProperty(name).SetValue(self, value, null);
}
public static void CopyPropertiesFrom(this MPropertySettable self, MPropertyGettable other) {
self.GetProperties().Intersect(other.GetProperties()).ToList().ForEach(
property => self.SetValue(property, other.GetValue(property)));
}
}
This way, all the code to achieve the property-copying is separate from the classes that use it. You just need to reference the mixins in their interface list.
Note that this is not as robust or flexible as AutoMapper, because you might want to copy properties with different names or just some sub-set of the properties. Or it might downright fail if the properties don't provide the necessary getters or setters or their types differ. But, it still might be enough for your purposes.
This is cheap and easy. It makes use of System.Web.Script.Serialization and some extention methods for ease of use:
public static class JSONExts
{
public static string ToJSON(this object o)
{
var oSerializer = new System.Web.Script.Serialization.JavaScriptSerializer();
return oSerializer.Serialize(o);
}
public static List<T> FromJSONToListOf<T>(this string jsonString)
{
var oSerializer = new System.Web.Script.Serialization.JavaScriptSerializer();
return oSerializer.Deserialize<List<T>>(jsonString);
}
public static T FromJSONTo<T>(this string jsonString)
{
var oSerializer = new System.Web.Script.Serialization.JavaScriptSerializer();
return oSerializer.Deserialize<T>(jsonString);
}
public static T1 ConvertViaJSON<T1>(this object o)
{
return o.ToJSON().FromJSONTo<T1>();
}
}
Here's some similiar but different classes:
public class Member
{
public string Name { get; set; }
public int Age { get; set; }
public bool IsCitizen { get; set; }
public DateTime? Birthday { get; set; }
public string PetName { get; set; }
public int PetAge { get; set; }
public bool IsUgly { get; set; }
}
public class MemberV2
{
public string Name { get; set; }
public int Age { get; set; }
public bool IsCitizen { get; set; }
public DateTime? Birthday { get; set; }
public string ChildName { get; set; }
public int ChildAge { get; set; }
public bool IsCute { get; set; }
}
And here's the methods in action:
var memberClass1Obj = new Member {
Name = "Steve Smith",
Age = 25,
IsCitizen = true,
Birthday = DateTime.Now.AddYears(-30),
PetName = "Rosco",
PetAge = 4,
IsUgly = true,
};
string br = "<br /><br />";
Response.Write(memberClass1Obj.ToJSON() + br); // just to show the JSON
var memberClass2Obj = memberClass1Obj.ConvertViaJSON<MemberV2>();
Response.Write(memberClass2Obj.ToJSON()); // valid fields are filled
For one thing I would not place that code (somewhere) external but in the constructor of the ViewModel:
class DefectViewModel
{
public DefectViewModel(Defect source) { ... }
}
And if this is the only class (or one of a few) I would not automate it further but write out the property assignments. Automating it looks nice but there may be more exceptions and special cases than you expect.
Any chance you could have both classes implement an interface that defines the shared properties?
I'm not even sure what this principle is called or how to search for it, so I sincerely apologize if it has been brought up before, but the best way to do it is with an example.
class Properties
{
public string Name { get; set; }
}
class MyClass
{
class SubProperties: Properties
{
public override Name
{
get { return GetActualName(); }
set { SetActualName(value); }
}
}
public SubProperties ClassProperties;
private string GetActualName()
{
return SomeFunction();
}
private void SetActualName(string s)
{
ClassProperties.Name = SomeOtherFunction(s);
}
}
The idea is to have any object that instantiates MyClass have a fully accessible property ClassProperties. To that object, it would look exactly like a Properties object, but behind the scenes, MyClass is actually computing and modifying the results of the fields. This method of declaration is obviously wrong since I can't access GetActualName() and SetActualName() from within the SubProperties definition. How would I achieve something like this?
Are you looking for something like this?
abstract class Properties
{
public abstract string Name { get; set; }
}
class MyClass
{
private class SubProperties : Properties
{
private MyClass myClass;
public SubProperties(MyClass myClass)
{
this.myClass = myClass;
}
public override Name
{
get { return this.myClass.GetActualName(); }
set { this.myClass.SetActualName(value); }
}
}
private string name;
public MyClass
{
this.MyClassProperties = new SubProperties(this);
}
public Properties MyClassProperties { get; private set; }
private string GetActualName()
{
return this.name;
}
private void SetActualName(string s)
{
this.name = s;
}
}
You need to pass a reference to a MyClass instance to the SubProperties instance if you want to access MyClass methods from SubProperties.
public virtual string Name { get; set; }
How can we implement the Builder
pattern of Joshua's
Effective Java in C#?
Below is the code I have tried, is there a better way to do this?
public class NutritionFacts
{
public static NutritionFacts.Builder Build(string name, int servingSize, int servingsPerContainer)
{
return new NutritionFacts.Builder(name, servingSize, servingsPerContainer);
}
public sealed class Builder
{
public Builder(String name, int servingSize,
int servingsPerContainer)
{
}
public Builder totalFat(int val) { }
public Builder saturatedFat(int val) { }
public Builder transFat(int val) { }
public Builder cholesterol(int val) { }
//... 15 more setters
public NutritionFacts build()
{
return new NutritionFacts(this);
}
}
private NutritionFacts(Builder builder) { }
protected NutritionFacts() { }
}
How do we extend such a class? Do
we need to write separate builder
classes for each of the derived
classes?
public class MoreNutritionFacts : NutritionFacts
{
public new static MoreNutritionFacts.Builder Build(string name, int servingSize, int servingsPerContainer)
{
return new MoreNutritionFacts.Builder(name, servingSize, servingsPerContainer);
}
public new sealed class Builder
{
public Builder(String name, int servingSize,
int servingsPerContainer) {}
public Builder totalFat(int val) { }
public Builder saturatedFat(int val) { }
public Builder transFat(int val) { }
public Builder cholesterol(int val) { }
//... 15 more setters
public Builder newProperty(int val) { }
public MoreNutritionFacts build()
{
return new MoreNutritionFacts(this);
}
}
private MoreNutritionFacts(MoreNutritionFacts.Builder builder) { }
}
In Protocol Buffers, we implement the builder pattern like this (vastly simplified):
public sealed class SomeMessage
{
public string Name { get; private set; }
public int Age { get; private set; }
// Can only be called in this class and nested types
private SomeMessage() {}
public sealed class Builder
{
private SomeMessage message = new SomeMessage();
public string Name
{
get { return message.Name; }
set { message.Name = value; }
}
public int Age
{
get { return message.Age; }
set { message.Age = value; }
}
public SomeMessage Build()
{
// Check for optional fields etc here
SomeMessage ret = message;
message = null; // Builder is invalid after this
return ret;
}
}
}
This isn't quite the same as the pattern in EJ2, but:
No data copying is required at build time. In other words, while you're setting the properties, you're doing so on the real object - you just can't see it yet. This is similar to what StringBuilder does.
The builder becomes invalid after calling Build() to guarantee immutability. This unfortunately means it can't be used as a sort of "prototype" in the way that the EJ2 version can.
We use properties instead of getters and setters, for the most part - which fits in well with C# 3's object initializers.
We do also provide setters returning this for the sake of pre-C#3 users.
I haven't really looked into inheritance with the builder pattern - it's not supported in Protocol Buffers anyway. I suspect it's quite tricky.
This blog entry might be of interest
A neat variation on the pattern in C# is the use of an implicit cast operator to make the final call to Build() unnecessary:
public class CustomerBuilder
{
......
public static implicit operator Customer( CustomerBuilder builder )
{
return builder.Build();
}
}
Edit: I used this again and simplified it to remove the redundant value-checking in setters.
I recently implemented a version that is working out nicely.
Builders are factories which cache the most recent instance. Derived builders create instances and clear the cache when anything changes.
The base class is straightforward:
public abstract class Builder<T> : IBuilder<T>
{
public static implicit operator T(Builder<T> builder)
{
return builder.Instance;
}
private T _instance;
public bool HasInstance { get; private set; }
public T Instance
{
get
{
if(!HasInstance)
{
_instance = CreateInstance();
HasInstance = true;
}
return _instance;
}
}
protected abstract T CreateInstance();
public void ClearInstance()
{
_instance = default(T);
HasInstance = false;
}
}
The problem we are solving is more subtle. Let's say we have the concept of an Order:
public class Order
{
public string ReferenceNumber { get; private set; }
public DateTime? ApprovedDateTime { get; private set; }
public void Approve()
{
ApprovedDateTime = DateTime.Now;
}
}
ReferenceNumber does not change after creation, so we model it read-only via the constructor:
public Order(string referenceNumber)
{
// ... validate ...
ReferenceNumber = referenceNumber;
}
How do we reconstitute an existing conceptual Order from, say, database data?
This is the root of the ORM disconnect: it tends to force public setters on ReferenceNumber and ApprovedDateTime for technical convenience. What was a clear truth is hidden to future readers; we could even say it is an incorrect model. (The same is true for extension points: forcing virtual removes the ability for base classes to communicate their intent.)
A Builder with special knowledge is a useful pattern. An alternative to nested types would be internal access. It enables mutability, domain behavior (POCO), and, as a bonus, the "prototype" pattern mentioned by Jon Skeet.
First, add an internal constructor to Order:
internal Order(string referenceNumber, DateTime? approvedDateTime)
{
ReferenceNumber = referenceNumber;
ApprovedDateTime = approvedDateTime;
}
Then, add a Builder with mutable properties:
public class OrderBuilder : Builder<Order>
{
private string _referenceNumber;
private DateTime? _approvedDateTime;
public override Order Create()
{
return new Order(_referenceNumber, _approvedDateTime);
}
public string ReferenceNumber
{
get { return _referenceNumber; }
set { SetField(ref _referenceNumber, value); }
}
public DateTime? ApprovedDateTime
{
get { return _approvedDateTime; }
set { SetField(ref _approvedDateTime, value); }
}
}
The interesting bit is the SetField calls. Defined by Builder, it encapsulates the pattern of "set the backing field if different, then clear the instance" that would otherwise be in the property setters:
protected bool SetField<TField>(
ref TField field,
TField newValue,
IEqualityComparer<T> equalityComparer = null)
{
equalityComparer = equalityComparer ?? EqualityComparer<TField>.Default;
var different = !equalityComparer.Equals(field, newValue);
if(different)
{
field = newValue;
ClearInstance();
}
return different;
}
We use ref to allow us to modify the backing field. We also use the default equality comparer but allow callers to override it.
Finally, when we need to reconstitute an Order, we use OrderBuilder with the implicit cast:
Order order = new OrderBuilder
{
ReferenceNumber = "ABC123",
ApprovedDateTime = new DateTime(2008, 11, 25)
};
This got really long. Hope it helps!
The reason to use Joshua Bloch's builder pattern was to create a complex object out of parts, and also to make it immutable.
In this particular case, using optional, named parameters in C# 4.0 is cleaner. You give up some flexibility in design (don't rename the parameters), but you get better maintainable code, easier.
If the NutritionFacts code is:
public class NutritionFacts
{
public int servingSize { get; private set; }
public int servings { get; private set; }
public int calories { get; private set; }
public int fat { get; private set; }
public int carbohydrate { get; private set; }
public int sodium { get; private set; }
public NutritionFacts(int servingSize, int servings, int calories = 0, int fat = 0, int carbohydrate = 0, int sodium = 0)
{
this.servingSize = servingSize;
this.servings = servings;
this.calories = calories;
this.fat = fat;
this.carbohydrate = carbohydrate;
this.sodium = sodium;
}
}
Then a client would use it as
NutritionFacts nf2 = new NutritionFacts(240, 2, calories: 100, fat: 40);
If the construction is more complex this would need to be tweaked; if the "building" of calories is more than putting in an integer, it's conceivable that other helper objects would be needed.