CA2229 Rules with a Model - catel

I was doing Code Analysis on my project and I got some warning on rule CA2229
Considering this snippet
[Serializable]
public partial class Split : ModelBase
{
private double? fx;
public int? Currency { get; set; }
public double? Fx
{
get
{
return this.fx;
}
set
{
this.fx = value;
RaisePropertyChanged(() => Fx);
}
}
}
should I implenent the constructor as suggested?
protected Split(SerializationInfo info, StreamingContext context)
{
}
Thanks

Note that the serializable part is only required when using binary serialization. In that case it's best to create 2 constructors:
public Split()
{
// Use when instantiating yourself
}
public Split(SerializationInfo info, StreamingContext context)
{
// Used by serialization
}

Related

How to apply AutoMapper ValueConverters against properties that may be null

I think this is an AutoMapper bug but the issue template they have in GitHub states to post something to SO first.
I want to be able to apply an IValueConverter without worrying about null exceptions.
As an example, I'm using a IValueConverter to apply some logic in multiple mappings:
public class ExampleConverter : IValueConverter<string, string>
{
public string Convert(string sourceMember, ResolutionContext context)
{
if (string.IsNullOrEmpty(sourceMember))
{
return string.Empty;
}
return sourceMember.ToUpper();
}
}
If I have the following types I'm mapping to and from:
public class ExampleSource
{
public ExampleNestedSource1 A { get; set; }
}
public class ExampleNestedSource1
{
public ExampleNestedSource2 B { get; set; }
}
public class ExampleNestedSource2
{
public string Input { get; set; }
}
public class ExampleDestination
{
public string Output { get; set; }
}
I can apply the converter like so:
public class ExampleProfile : Profile
{
public ExampleProfile()
{
this.CreateMap<ExampleSource, ExampleDestination>(MemberList.None)
.ForMember(dst => dst.Output, opt => opt.ConvertUsing(new ExampleConverter(), src => src.A.B.Input));
}
}
Using the converter like this however, throws an exception when A or B are null:
mapper.Map<ExampleDestination>(new ExampleSource // Throws null reference
{
A = new ExampleNestedSource1(),
});
mapper.Map<ExampleDestination>(new ExampleSource()); // Throws null reference
Because opt.ConvertUsing(new ExampleConverter(), src => src.A.B.Input) takes in an expression I can't use null propagating operators like src?.A?.B?.Input.
If I remove the converter and use MapFrom, the problem goes away:
public class ExampleProfile : Profile
{
public ExampleProfile()
{
this.CreateMap<ExampleSource, ExampleDestination>(MemberList.None)
.ForMember(dst => dst.Output, opt => opt.MapFrom(src => src.A.B.Input));
}
}
But MapFrom doesn't support IValueConverter it only supports IMemberValueResolver which is less reusable.
Is there a better way to handle this scenario?
If not, I'm thinking AutoMapper should either:
Add support for IValueConverter in the MapFrom method.
ConvertUsing should not invoke the given converter when the expression doesn't resolve to a property and not throw.
ConvertUsing should invoke the given converter with null when the expression doesn't resolve to a property (in the same way that MapFrom) and not throw.

structuremap object reference with particular dependency

I am new to structuremap.
I want to get Shopper classes object with either "master" or "visa" dependency based on user input.
In below code I have created two concrete classes MasterCard and Visa from ICreditCard. I am injecting dependency of ICreditCard but when code is executing based on user's option I want to inject MasterCard or Visa depdency to Shopper class and get reference of that Shopper class object.
Can someone tell me how to do it if it is possible. I also want to know if I want to initialise object in some other class then how to do it(is it by exposing a method returning container object?)
class Program
{
static void Main(string[] args)
{
var container = new Container();
container.Configure(c => c.For<ICreditCard>().Use<MasterCard>().Named("master"));
container.Configure(x => x.For<ICreditCard>().Use<Visa>().Named("visa"));
//how to get instance of Shopper with master card object reference?
Console.ReadKey();
}
public class Visa : ICreditCard
{
public string Charge()
{
return "Visa... Visa";
}
public int ChargeCount
{
get { return 0; }
}
}
public class MasterCard : ICreditCard
{
public string Charge()
{
ChargeCount++;
return "Charging with the MasterCard!";
}
public int ChargeCount { get; set; }
}
public interface ICreditCard
{
string Charge();
int ChargeCount { get; }
}
public class Shopper
{
private readonly ICreditCard creditCard;
public Shopper(ICreditCard creditCard)
{
this.creditCard = creditCard;
}
public int ChargesForCurrentCard
{
get { return creditCard.ChargeCount; }
}
public void Charge()
{
Console.WriteLine(creditCard.Charge());
}
}
}

inherited class AutoMapper.AutoMapperMappingException

I am new at automapper and it is a very good stuff easy to use, but now I have a problem with it. Trying to convert my derived class to base and it gives me
AutoMapper.AutoMapperMappingException
Missing type map configuration or unsupported mapping.
Mapping types: ClientEventDb -> EventId
Database.ClientEventDb -> EventId
Destination path: ClientEvent
Source value:
Event:Login
Automapper wants to convert ClientEventDb to EventId? I don't understand why. EventId is an enum...
Please help me I have run out of ideas.
Here is the code which I run:
ClientEventDb[] edbl;
using (var context = new DbEntities())
{
edbl=context.Events.Take(1000).ToArray();
}
Mapper.CreateMap<ClientEventDb, ClientEvent>();
Console.WriteLine("hello");
return edbl.Select(edb => Mapper.Map<ClientEvent>(edb)).ToArray();
Here are my classes
[Table("events", Schema = "public")]
public class ClientEventDb : ClientEvent
{
public ClientEventDb(string userName, EventId happening, object userObject = null)
: base(userName, happening, userObject)
{
}
public ClientEventDb()
{
}
}
[ProtoContract]
[Table("events", Schema = "public")]
public class ClientEvent : ClientEventBase
{
[ProtoMember(1)]
[Column("username")]
public string UserName { get; private set; }
[ProtoMember(2)]
[Column("time")]
public DateTime DateTime { get; private set; }
[ProtoMember(3)]
[Key]
[Column("id")]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public string Id { get; private set; }
[ProtoMember(4)]
[Column("data")]
public byte[] UserObject { get; set; }
public ClientEvent(string userName,EventId happening, object userObject=null) : base(happening)
{
UserName = userName;
DateTime = DateTime.Now;
//UserObject = null;
if (userObject!=null) throw new NotImplementedException();
}
public ClientEvent()
{
}
protected ClientEvent Clone()
{
return (ClientEvent)MemberwiseClone();
}
}
[ProtoContract]
[ProtoInclude(10, typeof(ClientEvent))]
public class ClientEventBase
{
[Column("eventid")]
[ProtoMember(1)]
public int EventIdValue { get; set; } //must be public because of entity framework
[NotMapped]
public EventId EventId
{
get { return (EventId) EventIdValue; }
set { EventIdValue = (int) value; }
}
public ClientEventBase(EventId eventId)
{
EventId = eventId;
}
public ClientEventBase()
{
}
public override string ToString()
{
return String.Format("Event:{0}",EventId);
}
}
public enum EventId
{
Login = 1,
Logout,
ExitApplication,
}
UPDATE
bugfix: ClientEvent [Key] attribute moved to id property
Solution was this (thx to stuartd):
ClientEventDb[] edbl;
using (var context = new DbEntities())
{
edbl=context.Events.ToArray();
}
Mapper.CreateMap<ClientEventDb, ClientEvent>().ConstructUsing((ClientEventDb src) => new ClientEvent());
return edbl.Select(Mapper.Map<ClientEvent>).ToArray();
AutoMapper is confused as its made to map between similar properties in different classes, you are using it incorrectly - you just need to go from the derived class to the base which does not require AutoMapper. You could use this to do what you need....
ClientEventDb[] edbl;
using (var context = new DbEntities())
{
edbl=context.Events.Take(1000).ToArray();
}
return edbl.Cast<ClientEvent>().ToList();
I'd be looking at why you even feel you need a derived ClientEventDb though - understand we dont have the whole picture here but it seems to do nothing in addition to what the base class already does.
The issue is that ClientEvent has two constructors but you have not told AutoMapper which to use.
If you want it to use your constructor with parameters, change your mapping code to this and it will work:
Mapper.CreateMap<ClientEventDb, ClientEvent>()
.ConstructUsing(src => new ClientEvent(src.UserName, src.EventId));
Or to make AutoMapper use the default constructor:
Mapper.CreateMap<ClientEventDb, ClientEvent>()
.ConstructUsing((ClientEventDb src) => new ClientEvent());

ServiceStack QueryBase class for Paging + Sorting, but Validation not fired

I've created a QueryBase class in order to support Paging and Sorting when needed.
public class QueryBase
{
public string Sort { get; set; }
public int PageNumber { get; set; }
public int PageSize { get; set; }
}
If a class supports these features, it'll simply extend it like this:
public class Cars: QueryBase, IReturn<CarsResponse>
{
}
public class CarsResponse : IHasResponseStatus
{
public List<Car> Cars { get; set; }
public ResponseStatus ResponseStatus { get; set; }
}
Then in order to fill QueryBase from querystring I've created a RequestFilterAttribute that can be used when needed:
public class QueryRequestFilterAttribute : Attribute, IHasRequestFilter
{
#region IHasRequestFilter Members
public IHasRequestFilter Copy()
{
return this;
}
public int Priority
{
get { return -100; }
}
public void RequestFilter(IHttpRequest req, IHttpResponse res, object requestDto)
{
var request = requestDto as QueryBase;
if (request == null) { return; }
request.PageNumber = req.QueryString["pageNumber"].IsEmpty() ? 1 : int.Parse(req.QueryString["pageNumber"]);
request.PageSize = req.QueryString["pageSize"].IsEmpty() ? 15 : int.Parse(req.QueryString["pageSize"]);
request.Sort = req.QueryString["sort"].IsNullOrEmpty() ? "id" : req.QueryString["sort"];
}
#endregion
}
Everything is working properly, but my goal now is to enable Validation in order to define some basic rules like maxpagesize or minpagenumber.
A very basic implementation is:
public class QueryBaseValidator : AbstractValidator<QueryBase>
{
public QueryBaseValidator()
{
RuleFor(query => query.PageSize).LessThanOrEqualTo(100).GreaterThan(0);
}
}
In this way validator filter is not able to find the validator above in its cache, because it searches for Cars instead of QueryBase (line 11 ValidationFilter.cs):
ValidatorCache.GetValidator(req, requestDto.GetType());
What is the best solution for this problem in order to avoid writing same validation logic in each subclass?
I found a solution but I don't know if it's the best one: using a validator for each class implementing QueryBase.
QueryBaseValidator modified as follows:
public class QueryBaseValidator<T> : AbstractValidator<T> where T : QueryBase
{
public QueryBaseValidator()
{
RuleFor(query => query.PageSize).LessThanOrEqualTo(100).GreaterThan(0);
}
}
Additional validator created for subclass Cars
public class CarsValidator : QueryBaseValidator<Cars>
{
}
In this way everything works and I've now a basic implementation of generic paging, sorting and very soon query with ServiceStack.

How to define a constraint on class type if It has custom attribute?

there is any way to force a class to implement an interface , if It has an specific custom attribute?
I want to have a compile time error , if the class with specific attribute does not implement an specific interface.
[myAttrib]
public MyClass:IMyInterface
{
}
If myClass is not typeof(IMyInterface) , I will get an error in compile time.
thanks,
In case of properties, You could create an abstract class inheriting the interface and gets your final class drive from that abstract class.
Have a look at
public interface Test
{
string Name { get; set; }
}
public abstract class Test1 : Test
{
public abstract string Name { get; set; }
}
public class Test2 : Test1
{
}
For custom attribute you could do
public class Alias : System.Attribute
{
string[] _types;
public Alias(params string[] types)
{
this.Types = types;
}
public Alias()
{
this.Types = null;
}
public string[] Types
{
get { return _types; }
set { _types = value; }
}
}
public interface Test
{
Alias Attrib{ get;}
}
public abstract class Test1 : Test
{
public abstract Alias Attrib { get; }
}
public class Test2 : Test1
{
}
Hope I answer your question.

Resources