This HttpRequestMessage Headers are assignable even that they are { get; } only - oop

Why do I get about this assignment into Headers this error
var request = new HttpRequestMessage()
{
Headers = default
};
Property or indexer 'property' cannot be assigned to -- it is read only
And it is the same even if i assign null.
And for the following code i dont get it, ain't it also an assignment of value to `Headers` property ?
var request = new HttpRequestMessage()
{
Headers = {}
};

{} is a collection initializer:
int[] fooBar = { };
I cannot find a proof that empty collection initializer {} can be assigned to readonly property which has reference type.
However, this code is valid:
public class FooBar
{
public object MyProperty { get; }
}
var foo = new FooBar()
{
MyProperty = { }
};

After some research it seems that if a property is read-only, items can be added to it using {}, this is the meaning of this operator, this is not an assignment to the property reference. for example:
public class ItemsContainer
{
public List<string> Items { get; } = new List<string> { "a" };
}
This code will producde:
ItemsContainer itemsContainer = new ItemsContainer()
{
Items = { "b" }
};
Console.WriteLine(string.Join(',', itemsContainer.Items));
Will have result of:
a,b
Which mean that it only adds to the collection.
If we change the implimitaitiom of ItemsContainer to:
public class ItemsContainer
{
public List<string> Items { get; }
}
For the same code a NullReferenceException will be thrown because you try to add to a collection which is not initialized and have a null value.
More info:
https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/object-and-collection-initializers#object-initializers-with-collection-read-only-property-initialization

You can't. That is what read-only properties are for. You cannot the change the actual reference, but you can change the value itself. Based on what the concrete type allows.
If you want to have the headers empty (which it looks like from your example), you just use request.Headers.Clear(). And other methods alike if you want to alter/add/etc. headers.

Related

how to make a custom error message with extension method in fluent validation

public class Validator : AbstractValidator<Command>
{
public Validator(ICheckExists<ICheckEntityExists> checkEntityExists)
{
RuleFor(x => x)
.EntityDoesNotExist(checkEntityExists, c => new CheckEntityExists()
{
TypeId = c.Id,
StatusId = c.StatusId
});
}
Hi, I Have a problem. The code above generates "must not exist" error message.
EntityDoesNotExist is an extension method that I can not change.Since it is an extension method I could not use any of this OverridePropertyName WithName WithMessage.
The question is how can I change the error message to a custom one.
I have written this code which does the thing
ValidatorOptions.Global.DisplayNameResolver = (type, member, expression) =>
{
if (member == null)
{
return "Hello world";
}
return member.Name;
};
But it works only if I have 1 rule that has no name and it looks not pretty.
Maybe there it is another way of achieving the same result?
The problem is that extension method you are using return an instance of IRuleBuilder<T, out TProperty> interface which doesn't contain definitions for method like WithMessage. This and other methods you mentioned are extension methods for IRuleBuilderOptions<T, TProperty> interface which inherits IRuleBuilder<T, out TProperty>.
So one of possible solutions is to wrap EntityDoesNotExist extension method into another method which will downcast the returned type to IRuleBuilderOptions<T, TProperty>
For example we have class called Person:
public class Person
{
public string Name { get; set; } = null!;
}
Extension method for Name property which returns IRuleBuilder type:
public static IRuleBuilder<T, string> ValidateNameLength<T>(this IRuleBuilder<T, string> ruleBuilder)
{
return ruleBuilder.Must(name => name.Length < 5).WithMessage("Incorrect length");
}
So we can wrap this method something like this:
public static IRuleBuilderOptions<T, string> ValidateNameLengthWrapper<T>(this IRuleBuilder<T, string> ruleBuilder)
{
return (IRuleBuilderOptions<T, string>) ruleBuilder.ValidateNameLength();
}
Then we can use WithMessage method to override error description:
public class Validator : AbstractValidator<Person>
{
public Validator()
{
CascadeMode = CascadeMode.Continue;
RuleFor(x => x.Name!).ValidateNameLengthWrapper().WithMessage("Name must be less than 5 characters");
}
}
But maybe would be better to write your own extension method or resolve the problem outside the validation context.

Add property to a DeserializeObject instance?

I am DeserializeObject json to object.
if this is the json:
{
"IsSuccess":true,
"ErrorDescription":"the descriptions"
}
and I do not know the class.
public T Get<T>(string p1)
{
var response=JsonConvert.DeserializeObject<T>(str);
//how to add property to response here?
return response
}
I want to add a property to response but I do not know if response is null or not.
and I do not know which class is it.
I think it can not so:
If there is BaseClass:
public class BaseResp
{
public bool IsSuccessStatus{get;set;}
}
and if T is inherited by BaseResp then can I add property to it?
If I can not add property to it then can I return a new instance of BaseResp ?
public T Get<T>(string p1)
{
var response=JsonConvert.DeserializeObject<T>(str);
if(response==null)
{
return new BaseResp();
}
}

A way around instantiating sub classes in super class

I have a base abstract class, which aggregates a bunch of items in a collection:
abstract class AMyAbstract
{
List<string> Items { get; private set; }
public AMyAbstract(IEnumerable<string> items)
{
this.Items = new List<string>(items);
}
}
There are a lot of subclasses, let's name them Foo, Bar, Baz, etc. They all are immutable. Now I need a merge() method, which will merge items of two objects like this:
abstract class AMyAbstract
{
// ...
public AMyAbstract merge(AMyAbstract other)
{
// how to implement???
}
}
Foo foo1 = new Foo(new string[] {"a", "b"});
Bar bar1 = new Bar(new string[] {"c", "d"});
Foo fooAndBar = foo1.merge(bar1);
// items in fooAndBar now contain: {"a", "b", "c", "d"}
Since the objects are immutable, the merge() method should not change the state of items field, but instead it should return a new object of the class uppon which it is called. My question is: how to judiciously implement the merge() method?
Problem 1: AMyAbstract is clearly not aware of specific constructors of the subclasses (dependency inversion principle), thus I cannot (or can I?) create instance of the sub class in a super class.
Problem 2: Implementing merge() method in each of the subclasses is a lot of code repetition (DRY rule).
Problem 3: Extracting the merge() logic to a entirely new class does not solve the DRY rule problem. Even using the visitor pattern it is a lot of copy/paste.
The problems presented above rule out any idea of implementation I might have had before I read about SOLID. (my life has been miserable since then ;)
Or is there an entirely different, out-of-the-box approch to achieve the merge of such objects?
I'd appreciate answer in C#, Java or even PHP.
EDIT: I think I left out a piece of valid information: event though there are a lot of different sub classes, they can (should) only be constructed in two, maybe three ways (as an implication of the single responsibility principle):
parameterless constructor
a constructor which accepts one IEnumerable<T> argument
a constructor which accepts array and some other modifier
This would put the visitor pattern back on the tablie if I could put a constraint on the constructors - for example by defining a constructor in an interface. But this is possible only in PHP. In Java or C# a constructor signature cannot be enforced, thus I cannot be certain of how I would instantiate a subclass. This is a good rule in general, because one could never predict of how author of the subclass would like the object be constructed, but in this particular case it might have been helpful. So a helper question would be: can I somehow enforce how a class is instantiated? Builder pattern sounds like way too much in this simple case, or does it?
You are right about dependency inversion rule and code duplication problems.
You can write the core implementation of the merge logic in your abstract class and give out the task of creating a new instance to the derived classes. Create an abstract method in your abstract class that will force all the children to implement it. The purpose is this method is to create a new instance of the class and return it. This method will be used by the super class to get a new instance and do the merging.
The resultant java code will look something like this
abstract class AMyAbstract {
// ...
public AMyAbstract merge(AMyAbstract other) {
AMyAbstract obj = getNewInstance();
// Do the merge
// Return the merged object.
}
protected abstract AMyAbstract getNewInstance();
}
class foo extends AMyAbstract {
protected foo getNewInstance() {
// Instantiate Foo and return it.
}
}
Hope this helps..
OBSOLETE, kept for reference (and shows how I arrived at the final solution), see code after EDIT below
I would say the builder pattern is the way to go. We just need a builder which keeps the instance but modifies the one field that needs to be changed.
If one wants to obtain (as shown in your code)
Foo fooAndBar = foo1.merge(bar1);
an additional generic type definition is needed (thus defining class AMyAbstract <T>) to be able to still produce the correct final type (instead of just seeing AMyAbstract as type for the fooAndBar) in the above call.
Note: merge method was renamed to MergeItems in the code below to make clear what is merged.
I specified different constructors for Foo and Bar, so that it is clear that they do not need to have the same number of parameters.
Actually to be truly immutable, the list should not be directly returned in the Items property as it could be modified by the caller (using new List(items).AsReadOnly() produced a ReadOnlyCollection, so I just used this one).
Code:
abstract class AMyAbstract<T> where T : AMyAbstract<T>
{
public ReadOnlyCollection<string> Items { get; private set; }
protected AMyAbstract(IEnumerable<string> items)
{
this.Items = new List<string>(items).AsReadOnly();
}
public T MergeItems<T2>(AMyAbstract<T2> other) where T2 : AMyAbstract<T2>
{
List<string> mergedItems = new List<string>(Items);
mergedItems.AddRange(other.Items);
ButWithItemsBuilder butWithItemsBuilder = GetButWithItemsBuilder();
return butWithItemsBuilder.ButWithItems(mergedItems);
}
public abstract class ButWithItemsBuilder
{
public abstract T ButWithItems(List<string> items);
}
public abstract ButWithItemsBuilder GetButWithItemsBuilder();
}
class Foo : AMyAbstract<Foo>
{
public string Param1 { get; private set; }
public Foo(IEnumerable<string> items, string param1)
: base(items)
{
this.Param1 = param1;
}
public class FooButWithItemsBuilder : ButWithItemsBuilder
{
private readonly Foo _foo;
internal FooButWithItemsBuilder(Foo foo)
{
this._foo = foo;
}
public override Foo ButWithItems(List<string> items)
{
return new Foo(items, _foo.Param1);
}
}
public override ButWithItemsBuilder GetButWithItemsBuilder()
{
return new FooButWithItemsBuilder(this);
}
}
class Bar : AMyAbstract<Bar>
{
public string Param2 { get; private set; }
public int Param3 { get; private set; }
public Bar(IEnumerable<string> items, string param2, int param3)
: base(items)
{
this.Param2 = param2;
this.Param3 = param3;
}
public class BarButWithItemsBuilder : ButWithItemsBuilder
{
private readonly Bar _bar;
internal BarButWithItemsBuilder(Bar bar)
{
this._bar = bar;
}
public override Bar ButWithItems(List<string> items)
{
return new Bar(items, _bar.Param2, _bar.Param3);
}
}
public override ButWithItemsBuilder GetButWithItemsBuilder()
{
return new BarButWithItemsBuilder(this);
}
}
class Program
{
static void Main()
{
Foo foo1 = new Foo(new[] { "a", "b" }, "param1");
Bar bar1 = new Bar(new[] { "c", "d" }, "param2", 3);
Foo fooAndBar = foo1.MergeItems(bar1);
// items in fooAndBar now contain: {"a", "b", "c", "d"}
Console.WriteLine(String.Join(", ", fooAndBar.Items));
Console.ReadKey();
}
}
EDIT
Perhaps a simpler solution would be to avoid the builder class, and instead have
abstract T ButWithItems(List<string> items);
directly in the base class, and implementing classes would just implement it as currently the builders do.
Code:
abstract class AMyAbstract<T> where T : AMyAbstract<T>
{
public ReadOnlyCollection<string> Items { get; private set; }
protected AMyAbstract(IEnumerable<string> items)
{
this.Items = new List<string>(items).AsReadOnly();
}
public T MergeItems<T2>(AMyAbstract<T2> other) where T2 : AMyAbstract<T2>
{
List<string> mergedItems = new List<string>(Items);
mergedItems.AddRange(other.Items);
return ButWithItems(mergedItems);
}
public abstract T ButWithItems(List<string> items);
}
class Foo : AMyAbstract<Foo>
{
public string Param1 { get; private set; }
public Foo(IEnumerable<string> items, string param1)
: base(items)
{
this.Param1 = param1;
}
public override Foo ButWithItems(List<string> items)
{
return new Foo(items, Param1);
}
}
class Bar : AMyAbstract<Bar>
{
public string Param2 { get; private set; }
public int Param3 { get; private set; }
public Bar(IEnumerable<string> items, string param2, int param3)
: base(items)
{
this.Param2 = param2;
this.Param3 = param3;
}
public override Bar ButWithItems(List<string> items)
{
return new Bar(items, Param2, Param3);
}
}
class Program
{
static void Main()
{
Foo foo1 = new Foo(new[] { "a", "b" }, "param1");
Bar bar1 = new Bar(new[] { "c", "d" }, "param2", 3);
Foo fooAndBar = foo1.MergeItems(bar1);
// items in fooAndBar now contain: {"a", "b", "c", "d"}
Console.WriteLine(String.Join(", ", fooAndBar.Items));
Console.ReadKey();
}
}
I'm a bit late to the party but as you have yet to accept an answer I thought I would add my own.
One of the key points is that the collection should be immutable. In my example I have exposed IEnumerable to facilitate this - the collection of items is immutable outside of the instance.
There are 2 ways I see this working:
a public default constructor
an internal Clone template method similar to #naveen's answer above
Option 1 is less code but really it depends whether an instance of AMyAbstract with no items and no way to change the items is something you want to allow.
private readonly List<string> items;
public IEnumerable<string> Items { get { return this.items; } }
public static T CreateMergedInstance<T>(T from, AMyAbstract other)
where T : AMyAbstract, new()
{
T result = new T();
result.items.AddRange(from.Items);
result.items.AddRange(other.Items);
return result;
}
Seems to satisfy all of your requirements
[Test]
public void MergeInstances()
{
Foo foo = new Foo(new string[] {"a", "b"});
Bar bar = new Bar(new string[] {"c", "d"});
Foo fooAndBar = Foo.CreateMergedInstance(foo, bar);
Assert.That(fooAndBar.Items.Count(), Is.EqualTo(4));
Assert.That(fooAndBar.Items.Contains("a"), Is.True);
Assert.That(fooAndBar.Items.Contains("b"), Is.True);
Assert.That(fooAndBar.Items.Contains("c"), Is.True);
Assert.That(fooAndBar.Items.Contains("d"), Is.True);
Assert.That(foo.Items.Count(), Is.EqualTo(2));
Assert.That(foo.Items.Contains("a"), Is.True);
Assert.That(foo.Items.Contains("b"), Is.True);
Assert.That(bar.Items.Count(), Is.EqualTo(2));
Assert.That(bar.Items.Contains("c"), Is.True);
Assert.That(bar.Items.Contains("d"), Is.True);
}
Whether you ultimately choose a default constructor or a template method the crux of this answer is that the Items only need to be immutable on the outside.
A neat solution based on #AK_'s comment:
tldr: The basic idea is to create a multiple merge methods for each aggregated filed instead of using a merge method for entire object.
1) we'd want a special list type for the purpose of aggregating the items inside AMyAbstract instances, so let's create one:
class MyList<T> extends ReadOnlyCollection<T> { ... }
abstract class AMyAbstract
{
MyList<string> Items { get; private set; }
//...
}
The advantage here is that we have a specialized list type for our purpose, which we can alter later.
2) instead of having a merge method for entire object of AMyAbstract we would want to use a method which merly merges the items of that object:
abstract class AMyAbstract
{
// ...
MyList<T> mergeList(AMyAbstract other)
{
return this.Items.Concat(other.Items);
}
}
Another advatage we gain: decomposition of the problem of merging entire object. So instead we break it into a small problems (merging just the aggregated list in this case).
3) and now we can create a merged object using any specialized constructor we might think of:
Foo fooAndBar = new Foo(foo1.mergeList(bar1));
Instead of returning the new instance of entire object we return only the merged list, which in turn can be used to create object of target class. Here we gain yet another advantage: deferred object instantiation, which is the main purpose of creational patterns.
SUMMARY:
So not only this solution solves the problems presended in the question, but provides additional advantages presented above.

Trouble with DataContractSerializer

I'm trying to make DataContract Serializer work with one of my class.
Here it is :
public class MyOwnObservableCollection<T> : ObservableCollection<T>, IDisposable
where T : IObjectWithChangeTracker, INotifyPropertyChanged
{
protected List<T> removedItems;
[DataMember]
public List<T> RemovedItems
{
get { return this.removedItems;}
set { this.removedItems = value;}
}
// Other code removed for simplification
// ...
//
}
It is important to understand that the RemovedItems list gets populated automatically when you remove an Item from the ObservableCollection.
Now serializing an instance of this class using the DataContractSerializer with one element in the removedItems list with the following code :
MyOwnObservableCollection<Test> _Test = new MyOwnObservableCollection<Test>();
DataContractSerializer dcs = new DataContractSerializer(typeof(MyOwnObservableCollection<Test>));
XmlWriterSettings settings = new XmlWriterSettings() { Indent = true };
string fileName = #"Test.xml";
Insurance atest = new Test();
atest.Name = #"sfdsfsdfsff";
_Test.Add(atest);
_Test.RemoveAt(0); // The Iitem in the ObservableCollection is moved to the RemovedItems List/
using (var w = XmlWriter.Create(fileName, settings))
{
dcs.WriteObject(w, _Test);
}
ends with nothing in the XML file :
<?xml version="1.0" encoding="utf-8"?>
<ArrayOfTest xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="MyNameSpace" />
Why is this public property ignored ? What have I missed here ?
TIA.
The problem here is that your class is derived from a collection, and as such, the DataContractSerializer serializes only its items, but not any extra properties, as stated here: No properties when using CollectionDataContract.
A workaround would be using the original (inherited) collection as a property, rather than inheriting from it:
public class MyOwnObservableCollection<T> : IDisposable
where T : IObjectWithChangeTracker, INotifyPropertyChanged
{
readonly ObservableCollection<T> originalCollection = new ObservableCollection<T>();
protected List<T> removedItems = = new List<T>();
[DataMember]
public List<T> RemovedItems
{
get { return this.removedItems;}
set { this.removedItems = value;}
}
[DataMember]
public ObservableCollection<T> OriginalCollection
{
get { return this.originalCollection; }
}
// ...
}

Ninject Cascading Inection with IList

I am trying to use Ninject to implement cascading injection into a class that contains an IList field. It seems that, unless I specifically specify each binding to use in the kernel.Get method, the IList property is always injected with a list of a single default object.
The following VSTest code illustrates the problem. The first test fails because the IList field contains one MyType object with Name=null. The second test passes, but I had to specifically tell Ninject what constructor arguments to use. I am using the latest build from the ninject.web.mvc project for MVC 3.
Does Ninject specifically treat IList different, or is there a better way to handle this? Note that this seems to only be a problem when using an IList. Createing a custom collection object that wraps IList works as expected in the first test.
[TestClass()]
public class NinjectTest
{
[TestMethod()]
public void ListTest_Fails_NameNullAndCountIncorrect()
{
var kernel = new Ninject.StandardKernel(new MyNinjectModule());
var target = kernel.Get<MyModel>();
var actual = target.GetList();
// Fails. Returned value is set to a list of a single object equal to default(MyType)
Assert.AreEqual(2, actual.Count());
// Fails because MyType object is initialized with a null "Name" property
Assert.AreEqual("Fred", actual.First().Name);
}
[TestMethod()]
public void ListTest_Passes_SeemsLikeUnnecessaryConfiguration()
{
var kernel = new Ninject.StandardKernel(new MyNinjectModule());
var target = kernel.Get<MyModel>(new ConstructorArgument("myGenericObject", kernel.Get<IGenericObject<MyType>>(new ConstructorArgument("myList", kernel.Get<IList<MyType>>()))));
var actual = target.GetList();
Assert.AreEqual(2, actual.Count());
Assert.AreEqual("Fred", actual.First().Name);
}
}
public class MyNinjectModule : NinjectModule
{
public override void Load()
{
Bind<IList<MyType>>().ToConstant(new List<MyType> { new MyType { Name = "Fred" }, new MyType { Name = "Bob" } });
Bind<IGenericObject<MyType>>().To<StubObject<MyType>>();
}
}
public class MyModel
{
private IGenericObject<MyType> myGenericObject;
public MyModel(IGenericObject<MyType> myGenericObject)
{
this.myGenericObject = myGenericObject;
}
public IEnumerable<MyType> GetList()
{
return myGenericObject.GetList();
}
}
public interface IGenericObject<T>
{
IList<T> GetList();
}
public class StubObject<T> : IGenericObject<T>
{
private IList<T> _myList;
public StubObject(IList<T> myList)
{
_myList = myList;
}
public IList<T> GetList()
{
return _myList;
}
}
public class MyType
{
public String Name { get; set; }
}
lists, collections and arrays are handled slightly different. For those types ninject will inject a list or array containing an instance of all bindings for the generic type. In your case the implementation type is a class which is aoutobound by default. So the list will contain one instance of that class. If you add an interface to that class and use this one the list will be empty.