generic method validating data using FluentValidation - c#

I am using FluentValidator in a C# project.
I would like to make a generic method that can validate data from 2 possible types:
public class MyClassAValidator : AbstractValidator<MyClassA> {...}
public class MyClassBValidator : AbstractValidator<MyClassB> {...}
public void MyMt<T>(T param)
{
AbstractValidator<T> validator = null;
if(param is MyClassA)
{
var validator = new MyClassAValidator(); // Generatescompiler error
}
else if (cCOSLDto is CCOSLLoyerDto)
{
validator = new MyClassBValidator(); // Generatescompiler error
}
ValidationResult result = validator.Validate(param);
}
Compiler cannot convert MyClassAValidator() or MyClassBValidator() to AbstractValidator
How can I handle this?
I suspect (just a suspicion though) that it would work if I set a base class to MyClassA and MyClassB. But I would like to avoid this if possible as MyClassA and MyClassB are actually DTO classes so I would prefer them to stay without inheritence relationship.

Actually, if you need to validate two different types of objects in one method, you dont have to mess with inheritance from a generic class.
There is an easy way to do this. Any Validate method returns ValidationResult, so you can use something like this:
using FluentValidation;
using FluentValidation.Results;
using System;
namespace FluentValidatorTranslation
{
class Program
{
static void Main(string[] args)
{
}
public ValidationResult MyMt<T>(T param)
{
ValidationResult result;
if(param is MyClassA myClassA)
{
var validator = new MyClassAValidator();
result = validator.Validate(myClassA);
}
else if (param is MyClassB myClassB)
{
var validator = new MyClassBValidator();
result = validator.Validate(myClassB);
}
else
{
throw new ArgumentException("Type not supported");
}
return result;
}
}
public class MyClassA { }
public class MyClassB { }
public class MyClassAValidator : AbstractValidator<MyClassA>
{
}
public class MyClassBValidator : AbstractValidator<MyClassB>
{
}
}

Related

C# Use generic that references itself in concrete class declaration

Coming from Java, I think I should be able to do something like this:
using System.Collections.Generic;
interface ICoord<T> where T : ICoord<T>
{
ICollection<T> GetNeighbors();
}
class SquareCoord : ICoord<SquareCoord>
{
public ICollection<SquareCoord> GetNeighbors() {
throw new System.NotImplementedException();
}
}
interface IGrid<T> where T : ICoord<T>
{
List<T> GetGrid();
}
// This works no problem (everything is concretely defined)
class SquareGrid : IGrid<SquareCoord>
{
public List<SquareCoord> GetGrid() {
throw new System.NotImplementedException();
}
}
class Grid : IGrid<ICoord>
{
public List<ICoord> GetGrid()
{
//do stuff
}
}
where the last class Grid should be able to operate and return a List of any (concrete implementation of) ICoord.
I have a small working example in Java. If I could get the equivalent (if possible) in C#, that would give me enough to go on.
public class Example {
private interface Index<T extends Index> {
List<T> GetNeighbors();
}
private static class SquareIndex implements Index<SquareIndex> {
public List<SquareIndex> GetNeighbors(){
return new ArrayList<>();
}
}
private interface Grid<T extends Index> {
List<T> GetGrid();
}
// Java does not require a type parameter to implement "Grid"
private static class MyGrid implements Grid {
// Java allows me to satisfy the requirements for implementing "Grid"
// without having a concrete type defined in the method declaration.
public List<? extends Index> GetGrid() {
final List<SquareIndex> result = new ArrayList<>();
result.add(new SquareIndex());
return result;
}
}
public static void main(String[] args) {
MyGrid g = new MyGrid();
g.GetGrid();
}
}
My excellent girlfriend just figured it out:
class MyGrid<T> : IGrid<T> where T : ICoord<T>
{
public List<T> GetGrid() {
throw new System.NotImplementedException();
}
}

How to call generic property from another generic method

Here is my generic method from which i want to return the class object
public class TestBase
{
public T NavigateandReturntheObject<T>() where T : new()
{
//do navigate to page stuff and return the page object
//previously it was - return new T();
//Now i want to do something like this
return PageObjectBase<T>.PageObject;
}
}
Above method calling the below static generic class which will handle object creation of a particular class
public static class PageObjectBase<T> where T : class, new()
{
private static T singleTonObject;
public static T PageObject
{
get
{
return InstanceCreation();
}
}
public static T InstanceCreation()
{
if (singleTonObject == null)
{
singleTonObject = new T();
}
return singleTonObject;
}
}
How can i call the PageObject property from my test base class please advice.
Note : I have searched forum and find answers relevant to generic method to another generic method calling.The same is achieved by reflection.Can we use reflection in my case too? If so how can we do it.
You can add another constraint 'class' to NavigateandReturntheObject
public T NavigateandReturntheObject<T>() where T : class,new()
Complete Code.
public class TestBase
{
public T NavigateandReturntheObject<T>() where T : class,new()
{
//do navigate to page stuff and return the page object
//previously it was - return new T();
//Now i want to do something like this
return PageObjectBase<T>.PageObject;
}
}
Demo Code
public class TestClass
{
public string Name{get;set;}
public TestClass()
{
Name = "Dummy Name";
}
}
var testBase = new TestBase();
var sample = testBase.NavigateandReturntheObject<TestClass>();
Console.WriteLine(sample.Name);
Output
Dummy Name

Can I use generic getter/setter methods on multiple lists of same base types in C#

I want to know if there is a way I can create generic getter and setter methods for the below code.
Currently the setter checks the actual type of the input object and adds it to the relevant list. It feels like a bad approach to me, but I'd like to know if there is a better way.
I can't use any other data structures like a dictionary because I am using a serialisation system that can only serialise simple collection types like Lists and arrays, hence all the individual lists.
public abstract class BaseStyleType {}
public class ImageStyle : BaseStyleType {}
public class TextStyle : BaseStyleType {}
public class ButtonStyle : BaseStyleType {}
//...etc
public class GlobalStyle : ASerializedObject
{
public List<ImageStyle> ImageStyles = new List<ImageStyle>();
public List<TextStyle> TextStyles = new List<TextStyle>();
public List<ButtonStyle> ButtonStyles = new List<ButtonStyle>();
//... etc
// Setter
public void SetStyle(BaseStyleType inStyle)
{
if (inStyle as ImageStyle != null)
ImageStyles.Add((ImageStyle)inStyle);
else if (inStyle as TextStyle != null)
TextStyles.Add((TextStyle)inStyle);
else if (inStyle as ButtonStyle != null)
ButtonStyles.Add((ButtonStyle)inStyle);
//... etc
}
// Getter
public T GetStyle<T>(int index)
{
//...?
}
}
Thanks
Just because you can't use things for serialization purposes shouldn't prevent you from actually using them.
The advantage to the following solution is you can infinitely create derives classes from BaseStyleType (or other super types) and you'd only have to create the properties to access the dictionary.
public abstract class BaseStyleType {}
public class ImageStyle : BaseStyleType {}
public class TextStyle : BaseStyleType {}
public class ButtonStyle : BaseStyleType {}
// NOT THREAD SAFE
public class GlobalStyle
{
//
private Dictionary<Type,List<BaseStyleType>> _lists =
new Dictionary<Type,List<BaseStyleType>>();
// Not sure why you'd use Fields here...
public IEnumerable<ImageStyle> ImageStyles
{
get
{
IEnumerable<ImageStyle> result = null;
List<BaseStyleType> list;
if (_lists.TryGetValue(typeof(ImageStyle), out list))
{
result = list.Cast<ImageStyle>();
}
return result;
}
}
//etc
//public List<ImageStyle> ImageStyles = new List<ImageStyle>();
//public List<TextStyle> TextStyles = new List<TextStyle>();
//public List<ButtonStyle> ButtonStyles = new List<ButtonStyle>();
// Setter
public void SetStyle<T>(T inStyle)
where T : BaseStyleType
{
List<BaseStyleType> list;
if (_lists.TryGetValue(typeof(T), out list))
{
list.Add(inStyle);
}
else
{
list = new List<BaseStyleType>();
list.Add(inStyle);
_lists.Add(typeof(T), list);
}
}
}
I see two ways at least:
1) You got a simple, flat herarchy. Make only lists of BaseStyleType. Let covariance and automatic upcasting take care of the details.
2) Modify your code somewhat like that:
public abstract class BaseStyleType {}
public class ImageStyle : BaseStyleType {}
public class TextStyle : BaseStyleType {}
public class ButtonStyle : BaseStyleType {}
//...etc
public class GlobalStyle <List1Type, List2Type, List3Type, ... > : ASerializedObject
{
public List<List1Type> ImageStyles = new List<List1Type>();
public List<List2Type> TextStyles = new List<List2Type>();
public List<List3Type> ButtonStyles = new List<List3Type>();
//... etc
// Setter
public void SetStyle(BaseStyleType inStyle)
{
if (inStyle as ImageStyle != null)
ImageStyles.Add((ImageStyle)inStyle);
else if (inStyle as TextStyle != null)
TextStyles.Add((TextStyle)inStyle);
else if (inStyle as ButtonStyle != null)
ButtonStyles.Add((ButtonStyle)inStyle);
//... etc
}
// Getter
public T GetStyle<T>(int index)
{
//...?
}
}
The problem with long type lists is that you end up having to use lines like
GlobalStyle <ImageStyle , TextStyle, ButtonStyle> every single time a the type is needed (field types, return types, paramters, etc.). Starting with two generic placeholders, it is usually a good idea to make a type alias.
using CustomGlobalStyle = GlobalStyle <ImageStyle, TextStyle, ButtonStyle>;

Why do I need to declare the type?

I have the following code:
public interface IMyActionFactory
{
AbstractAction<T> CreateAction<T>(MyActionParamBase paramBase = null)
where T : MyActionParamBase;
}
public sealed class MergeActionParam : MyActionParamBase
{
}
public class MergeTest
{
private readonly IMyActionFactory _actionFactory = new DefaultMyActionFactory();
[Theory]
[PropertyData("MergeWorksData")]
public void MergeWorks(/*params here*/)
{
var param = new MergeActionParam();
// populate param here
var sut = _actionFactory.CreateAction<MergeActionParam>(param);
sut.DoAction();
}
}
I am getting an error
"..Error 10 Using the generic type 'IMyActionFactory' requires 1
type arguments..."
Why does the compiler expect a type to be passed to my IMyActionFactory, since I have declared the interface without a T? As far as the method is concerned its the only one to expect the type. Am I missing something here?
How can I make it work without redefining the interface signature?
EDIT:
Feeling a bit embarassed here, because the quick code I put down and ran seperately in a standalone online c# compiler doesnt give any compilation errors. However, going back to my original solution (tens of projects altogether) the error is still there.. Maybe has something to do with the XUnit ?..not sure
public interface IMyActionFactory
{
AbstractAction<T> CreateAction<T>(MyActionParamBase paramBase = null)
where T : MyActionParamBase;
}
public interface IAction
{
void DoAction();
}
public abstract class AbstractAction<T> : IAction
where T : MyActionParamBase
{
public void DoAction()
{
}
}
public class MyActionParamBase
{
public MyActionParamBase()
{
}
}
public sealed class MergeActionParam : MyActionParamBase
{
}
public class DefaultMyActionFactory : IMyActionFactory
{
public AbstractAction<T> CreateAction<T>(MyActionParamBase paramBase = null) where T : MyActionParamBase
{
return null;
}
}
public class MergeTest
{
private readonly IMyActionFactory _actionFactory = new DefaultMyActionFactory();
public void MergeWorks(/*params here*/)
{
var param = new MergeActionParam();
// populate param here
var sut = _actionFactory.CreateAction<MergeActionParam>(param);
sut.DoAction();
}
}

C# cast generic T in abstract class<T> to dynamic

This is what I want to do in C# (within class Helper - without generic arguments),
List<AbstractClass<dynamic>> data;
public void Add<T>(AbstractClass<T> thing)
{
this.data.Add((AbstractClass<dynamic>) thing);
}
This helper class would take and work with AbstractClass<> objects and give back AbstractClass<> of specific generic type. AbstractClass<T> contains many functions which return T / take in T like public T Invoke().
For Helper class T cannot be known beforehand. The Add<T>(.. thing) function is not in a class of type T.
To be used like this in Helper class's functions,
foreach(var c in data.Where(x => ...))
{
// public T Invoke() { ... } function within AbstractClass<T>
var b = c.Invoke();
// logic
}
This also fails,
List<AbstractClass<object>> data;
public void Add<T>(AbstractClass<T> thing)
{
this.data.Add((AbstractClass<object>) thing);
}
Now I think I can have,
List<dynamic> data; // or List<object> data;
public void Add<T>(AbstractClass<T> thing)
{
this.data.Add(thing);
}
but I want the constraint that List named data has only elements of type like
ConcreteClass : AbstractClass<OtherClass>
So we would know that there is an public T Invoke() function but we do not know what it returns. This is helpful to avoid mistakes of say misspelling Invocke and only knowing at run-time.
I want to avoid casting to dynamic every time to invoke functions that give back generic type T
To do what you want to do you are going to need to use a Contravariant interface
public class Program
{
static void Main()
{
var m = new Helper();
m.Add(new ConcreteClass());
m.Process();
}
class Helper
{
List<IAbstractClass<OtherClassBase>> data = new List<IAbstractClass<OtherClassBase>>();
public void Add(IAbstractClass<OtherClassBase> thing)
{
this.data.Add(thing);
}
public void Process()
{
foreach(var c in data.Where(x => x.ShouldBeProcessed()))
{
var b = c.Invoke();
Console.WriteLine(b.Question);
var castData = b as OtherClass;
if (castData != null)
Console.WriteLine(castData.Answer);
}
}
}
public interface IAbstractClass<out T>
{
bool ShouldBeProcessed();
T Invoke();
}
abstract class AbstractClass<T> : IAbstractClass<T>
{
public bool ShouldBeProcessed()
{
return true;
}
public abstract T Invoke();
}
class ConcreteClass : AbstractClass<OtherClass>
{
public override OtherClass Invoke()
{
return new OtherClass();
}
}
class OtherClassBase
{
public string Question { get { return "What is the answer to life, universe, and everything?"; } }
}
class OtherClass : OtherClassBase
{
public int Answer { get { return 42; } }
}
}
You do not need to tell Add what kind of class you are passing it, all that matters is it derives from the type specified. You could do public void Add(IAbstractClass<object> thing) and every class would work, but Invoke() would only return objects inside the foreach loop.
You need to figure out what is the most derived class you want Invoke() to return and that is what you set as the type in the list.
Maybe this will work for you:
public class Program
{
static void Main()
{
var m1 = new Helper<OtherClass>();
m1.Add(new ConcreteClass());
var m2 = new Helper<int>();
m2.Add(new ConcreteClass2());
}
class Helper<T>
{
List<AbstractClass<T>> data = new List<AbstractClass<T>>();
public void Add<T1>(T1 thing) where T1 : AbstractClass<T>
{
this.data.Add(thing);
}
}
class AbstractClass<T> { }
class OtherClass { }
class ConcreteClass : AbstractClass<OtherClass> { }
class ConcreteClass2 : AbstractClass<int> { }
}

Categories

Resources