Specifics of calling a method from the Parent Class - c#

My question is simple.
I am working with a testcase given to me in C#.
In this test case they have a Parent class containing all the methods and subclasses that will call those methods.
So as far as I know. You can do that by:
Class object = new Class(arguments);
Then call the parent methods like this object.Method()
Now the test I am working with has it written like this: Class.Method()
So just to make my question more clear here is an example of what they have:
Book harryPotterBook = new Book { title = "Harry Potter" };
var savedBook = Book.Find(harryPotterBook.Id);
and here is what I understand it should be:
var savedBook = harryPotterBook.Find(harryPotterBook.Id);
So is this possible? I just want to know what I am missing here.
Thank you.

I'm not sure I understand what you're trying to do right now, because in your example, you seem to be asking how to generate a class with a constructor. If you want to create a class constructor you have to write it like this:
public class Class
{
string name;
public Class(string pName)
{
name = pName;
}
}
Otherwise, if you know that this class is going to be used often as a standard. You can use interfaces:
interface IBasicClass
{
string name { get; set; }
string description { get; set; }
int numberOfPage { get; set; }
int currentPage { get; set; }
void NextPage();
void PreviousPage();
}
public class BasicClass : IBasicClass
{
public string name { get; set; }
public string description { get; set; }
public int numberOfPage { get; set; }
public int currentPage { get; set; }
//Default Constructor
public BasicClass()
{
name = "";
description = "";
numberOfPage = 0;
currentPage = 0;
}
//Constructor
public BasicClass(string pName, string pDescription, int pNumberOfPage)
{
name = pName;
description = pDescription;
numberOfPage = pNumberOfPage;
}
public void PreviousPage()
{
--currentPage;
}
public void NextPage()
{
++currentPage;
}
}
public class Class : MonoBehaviour
{
BasicClass _basicClass;
BasicClass _basicClass2;
void Start()
{
_basicClass = new BasicClass();
_basicClass2 = new BasicClass("Books", "It's a good book", 1);
}
void Update()
{
_basicClass.NextPage();
_basicClass2.NextPage();
}
}

Related

How to Create a generic method with 1 known property. Want to dynamic get the properties in different class with Generic Class property

I want to practice code with DRY principle, but my method uses 2 different classes, classOneDTO and classTwoDTO.. They have different properties and I want to linked it with PRIMARYIDENTIFIER prop with both have the same..
How can I create a generic method to get the property that I want to query with Linq.
Updated: my purpose is to have a generic method that will query the PrimaryIdentifier and get the data to it whether they are using classOneDTO or classTwoDTO. Is there a way to have a single generic method to do this?
private void genericMethod<T>(List<T> workList, GridView grid, int columnNo)
{
if (workList.Any())
{
string CodeString = default;
// Want to dynamic get the properties in different class with PrimaryIDentifier property
// want to check if PrimaryIdentifier is NULL OR EMPTY
var getDataOne = workList.Cast<classOneDTO>().FirstOrDefault(x => !string.IsNullOrEmpty(x.PrimaryIdentifier));
// causing error because of the CAST if wrong type request
var getDataTwo = workList.Cast<classTwoDTO>().FirstOrDefault(x => !string.IsNullOrEmpty(x.PrimaryIdentifier));
if (getDataOne != null || getDataTwo != null)
{
CodeString = (getDataOne != null) ? getDataOne.PrimaryIdentifier : getDataTwo.PrimaryIdentifier;
}
}
}
public class classOneDTO
{
public int PatientID { get; set; }
public string PrimaryIdentifier { get; set; }
public string FirstName{ get; set; }
// so oonnn...
}
public class classTwoDTO
{
public int EntryID { get; set; }
public string PrimaryIdentifier { get; set; }
public string Location{ get; set; }
// so oonnn...
}
All that you need is to make both your classes implement the same interface, i.e. IDTO:
public interface IDTO
{
string PrimaryIdentifier { get; set; }
}
Then you can tell the compiler to accept only types that implement your new interface:
private void GenericMethod<DTO>(List<DTO> workList, GridView grid, int columnNo)
where DTO: IDTO
{
if (workList.Any())
{
string CodeString = default;
var getData = workList.FirstOrDefault(x => !string.IsNullOrEmpty(x.PrimaryIdentifier));
if (getData != null)
{
CodeString = getData?.PrimaryIdentifier;
}
}
}
(Pay attention to the 2nd row)
Additionally, I also made minor adjustments to your class and method namings based on standard .Net naming convention.
Here's the full code:
public class Client
{
private void GenericMethod<DTO>(List<DTO> workList, GridView grid, int columnNo)
where DTO: IDTO
{
if (workList.Any())
{
string CodeString = default;
var getData = workList.FirstOrDefault(x => !string.IsNullOrEmpty(x.PrimaryIdentifier));
if (getData != null)
{
CodeString = getData?.PrimaryIdentifier;
}
}
}
}
public class ClassOneDTO : IDTO
{
public int PatientID { get; set; }
public string PrimaryIdentifier { get; set; }
public string FirstName { get; set; }
// so oonnn...
}
public class ClassTwoDTO : IDTO
{
public int EntryID { get; set; }
public string PrimaryIdentifier { get; set; }
public string Location { get; set; }
// so oonnn...
}
public interface IDTO
{
string PrimaryIdentifier { get; set; }
}
EDIT: as Johnathan Barclay correctly pointed out, there's actually no need to have a generic method if you don't need some more advanced logic there that you didn't show in your example.
private void GenericMethod(IEnumerable<IDTO> workList, GridView grid, int columnNo)
{
if (workList.Any())
{
string CodeString = default;
var getData = workList.FirstOrDefault(x => !string.IsNullOrEmpty(x.PrimaryIdentifier));
if (getData != null)
{
CodeString = getData?.PrimaryIdentifier;
}
}
}

Opinions on mapping fields of nested/hierarchical objects to flat list?

I'm writing a tool which accesses a word document to prefill it with data. The document has a subset of custom document properties, each identified by a name, whose values are used to update fields in the document.
My ViewModel should both be able to initiate/update its instances from data of those document properties, aswell as write its values back and update the fields of the document.
Something like this:
class PersonVM : INotifyPropertyChanged
{
// properties
string Name { get; set; }
string PhoneNumber { get; set; }
// methods to get data or save data of this properties to or from the word document
void saveMyPropertyValuesToWord()
{
// …
}
void updateMyPropertiesFromWord()
{
// …
}
}
class ProjectVM : INotifyPropertyChanged
{
int ProjectNumber { get; set; }
PersonVM Manager { get; set; }
PersonVM Mechanic1 { get; set; }
PersonVM Mechanic2 { get; set; }
void saveMyPropertyValuesToWord()
{
Manager.saveMyPropertyValuesToWord();
Mechanic1.saveMyPropertyValuesToWord();
Mechanic2.saveMyPropertyValuesToWord();
// handle ProjectNumber etc.
}
void updateMyPropertiesFromWord()
{
Manager.updateMyPropertiesFromWord();
Mechanic1.updateMyPropertiesFromWord();
Mechanic2.updateMyPropertiesFromWord();
// handle ProjectNumber etc.
}
class CompanyVM : INotifyPropertyChanged
{
string Name { get; set; }
PersonVM Owner { get; set; }
ProjectVM Project1 { get; set; }
ProjectVM Project2 { get; set; }
// …
}
// …
}
Right now I have a class with static string properties for each document property that might be present in a word document from which I would like to load the data accordingly:
class WordUtils
{
// Company
static string CompanyName = "dp_CompanyName";
// Company.Owner
static string CompanyOwnerName = "dp_CompanyOwnerName";
static string CompanyOwnerPhone = "dp_CompanyOwnerPhone";
// Company.Project1
static string CompanyProject1Number = "dp_CompanyProject1Number";
// Company.Project1.Manager
static string CompanyProject1ManagerName = "dp_CompanyProject1ManagerName";
static string CompanyProject1ManagerPhone = "dp_CompanyProject1ManagerPhone";
// Company.Project1.Mechanic1
// … etc
}
Now back to implementing those PersonVM.saveMyPropertyValuesToWord() - I thought of something like this:
void saveMyPropertyValuesToWord()
{
Name = MyApp.MyWordDocument.GetCustomProperty(WordUtils.OwnerName);
}
but here I need to know on class Level exactly what instance of it this is called from (i.e. what PersonVM am I, Company.Owner or Project1.Manager or ?) in order to decide which WordUtils.Name I need to provide.
I'm not sure how this should be done, maybe make PersonVM abstract and make a new class for each role (which would again only have one instance of itself, not very pretty in my eyes)? I have also taken a short look at Attributes and expect those might be helpfull in this scenario. Maybe I am missing something obvious, but extensive search for a robust way to tackle this problem have been fruitless so far.
How about something like this:
class Property
{
public string Key { get; }
public string Value { get; set; }
public Property(string key) => Key = key;
}
interface IPropertyTree
{
IEnumerable<IPropertyTree> ChildNodes { get; }
IEnumerable<Property> Properties { get; }
}
class PersonVM : IPropertyTree
{
private readonly string prefix;
public PersonVM(string prefix)
{
Name = new Property(prefix + "Name" );
PhoneNumber = new Property(prefix + "PhoneNumber");
}
public Property Name { get; }
public Property PhoneNumber { get; }
public IEnumerable<IPropertyTree> ChildNodes => Enumerable.Empty<IPropertyTree>();
public IEnumerable<Property> Properties => new[] {Name, PhoneNumber};
}
static class PropertyTreeExtensions
{
public static void Update(this IPropertyTree self)
{
foreach (var property in self.Flatten().SelectMany(tree => tree.Properties))
{
property.Value = MyApp.MyWordDocument.GetCustomProperty(property.Key);
}
}
public static IEnumerable<IPropertyTree> Flatten(this IPropertyTree self)
{
var stack = new Stack<IPropertyTree>();
stack.Push(self);
while (stack.Count > 0)
{
var current = stack.Pop();
yield return current;
foreach (var child in current.ChildNodes)
{
stack.Push(child);
}
}
}
}
This should allow each property to have a unique key, and keep the key and property value tightly coupled. It should also allow you to move the save/update logic to a centralized place.
Of course you can implement a concrete class of IPerson for each type and hard code the individual implementations.
Since you know the person type the moment you are creating an instance of PersonVMM, you could add an attribute PersonTypeId and set it from the constructor,
void SomeMethod()
{
var personVm = new PersonVM(WordUtils.OwnerName);
}
class PersonVM : INotifyPropertyChanged
{
// properties
string PersonTypeId { get; set; }
string Name { get; set; }
string PhoneNumber { get; set; }
public PersonVM()
{}
public PersonVM(string personTypeId)
{
PersonTypeId = personTypeId;
}
// methods to get data or save data of this properties to or from the word document
void saveMyPropertyValuesToWord()
{
Name = MyApp.MyWordDocument.GetCustomProperty(PersonTypeId);
}
}

How to access List<Interface> object properties when it's class is inherited from interface?

Ok, so here's the problem. I have an interface IBook, which includes property Name. There is two classes which inherit from the IBook and add their own property Genre. I wanna create a Dictionary or a List and add all kinds of books there and access them by string and their properties so I made it Dictionary. In the example, I can access books["LOTR"].Name but not books["LOTR"].Genre, propably because Name is property of the IBook interface but Genre is property of the class that inherits from the IBook.
Is it possible to make the Dictionary or List work with the interface type and still be able to access all the inheriting class properties as well, or should I use an array or something?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp124
{
interface IBook
{
string Name { get; set; }
}
public class FantasyBook:IBook
{
string name;
string genre;
public string Name
{
get { return name; }
set { name = value; }
}
public string Genre
{
get { return genre; }
set { genre = value; }
}
}
public class HorrorBook : IBook
{
string name;
string genre;
public string Name
{
get { return name; }
set { name = value; }
}
public string Genre
{
get { return genre; }
set { genre = value; }
}
}
class Program
{
static void Main(string[] args)
{
FantasyBook LordOfTheRings = new FantasyBook();
HorrorBook Frankenstein = new HorrorBook();
Dictionary<string, IBook> books = new Dictionary<string,
IBook>();
books.Add("LOTR", LordOfTheRings);
books.Add("Frankenstein", Frankenstein);
books["LOTR"].Name = "Lord Of The Rings";
books["LOTR"].Genre = "Fantasy";
Console.ReadLine();
}
}
}
An alternative approach is to add another layer of interface with Genre and use pattern matching for accessing the properties:
interface IBook
{
string Name { get; set; }
}
interface IBookWithGenre : IBook
{
string Genre { get; set; }
}
public class FantasyBook : IBookWithGenre
{
public string Name { get; set; }
public string Genre { get; set; }
}
public class HorrorBook : IBookWithGenre
{
public string Name { get; set; }
public string Genre { get; set; }
}
public class SimpleBook : IBook
{
public string Name { get; set; }
}
class Program
{
static void Main(string[] args)
{
FantasyBook LordOfTheRings = new FantasyBook();
HorrorBook Frankenstein = new HorrorBook();
SimpleBook abook = new SimpleBook();
var books = new Dictionary<string, IBook>
{
{ "LOTR", LordOfTheRings },
{ "Frankenstein", Frankenstein },
{ "Simple", abook },
};
books["LOTR"].Name = "Lord Of The Rings";
if (books["LOTR"] is IBookWithGenre withGenre)
{
withGenre.Genre = "Fantasy";
}
Console.ReadLine();
}
}
The comments are pretty much on point - you cannot do that as the compiler will examine available members on the IBook (since you declared it) and will not let you shoot yourself in the foot by trying to access a property that's not defined there. This is static type checking.
But let's for a second imagine you don't care about type safety and performance. It turns out, you have an option then. Well, sort of...as you will still have to give up your specific IBook for dynamic
interface IBook {
string Name { get; set; }
}
public class FantasyBook : IBook
{
public string Name { get; set; }
public string Genre { get; set; }
}
public class HorrorBook : IBook
{
public string Name {get;set;}
public string Genre {get;set;}
}
public class BadaBook : IBook // so I added this new class that does not implement Genre to illustrate a point
{
public string Name { get; set; }
}
static void Main(string[] args)
{
var LordOfTheRings = new FantasyBook();
var Frankenstein = new HorrorBook();
var Badaboom = new BadaBook();
Dictionary<string, dynamic> books = new Dictionary<string, dynamic>();
books.Add("LOTR", LordOfTheRings);
books.Add("Frankenstein", Frankenstein);
books.Add("Badaboom", Badaboom);
books["LOTR"].Name = "Lord Of The Rings";
books["LOTR"].Genre = "Fantasy";
books["Badaboom"].Name = "We can easily assign Name as it is defined. No problem here";
books["Badaboom"].Genre = "But we will miserably fail here"; // RuntimeBinderException: 'UserQuery.BadaBook' does not contain a definition for 'Genre'
Console.ReadLine();
}
Check out dynamic for further reading. It comes with the risks outlined in my example as well as performance penalties. It's not bad per se, it just needs to be taken in moderation.

Invalid initializer member declarator in unit test mock up

I have a class
public class Restrictions
{
[Key]
public short RestrictionId { get; set; }
public string Description { get; set; }
public string BlockCode { get; set; }
public List<CustomerRestrictions> CustomerRestrictions { get; set; }
}
And
public class CustomerRestrictions
{
public int CustomerId { get; set; }
public CustomerContacts CustomerContacts { get; set; }
public string RestrictionId { get; set; }
public Restrictions Restrictions { get; set; }
}
Then
public class CustomerContacts
{
[Key]
public long CustomerId { get; set; }
public string Btn { get; set; }
public List<CustomerRestrictions> CustomerRestrictions { get; set; }
}
It seems to be many-to-many relationship.
Now I want to do a unit test for the controller. There is a similar example.
But it doesn't have many to many.
My controller is
[Route("api/[controller]")]
public class BtnRulesController : Controller
{
private readonly IBtnRulesRepository _btnRulesRepository;
public BtnRulesController(IBtnRulesRepository btnRulesRepository)
{
_btnRulesRepository = btnRulesRepository;
}
// GET api/BtnRules
[HttpGet]
public IList<Restrictions> Get()
{
return _btnRulesRepository.GetRestrictions();
}
The difficult thing is how to create sample data in unit test at this moment.
public class SimpleBtnRulesControllerTest
{
[Fact]
public void GetAllBtnRules_Should_Return_All_BtnRules()
{
var repo = new Mock<IBtnRulesRepository>().Object;
var controller = new BtnRulesController(repo);
var testBtnRules = GetTestBtnRules();
var result = controller.Get();
Assert.Equal(testBtnRules.Count,result.Count);
}
public List<Restrictions> GetTestBtnRules()
{
var testBtnRules = new List<Restrictions>();
var testCustomerRestrictionsList = new List<CustomerRestrictions>();
var testCustomerRestrictions = new CustomerRestrictions();
testCustomerRestrictions.CustomerId = 1;
testCustomerRestrictions.RestrictionId = "1";
testCustomerRestrictions.Restrictions=new Restrictions();
testCustomerRestrictions.CustomerContacts=new CustomerContacts();
testCustomerRestrictionsList.Add(new CustomerRestrictions());
testBtnRules.Add(new Restrictions() {RestrictionId = 1, Description = "Demo1",BlockCode = "AdminBlock1",testCustomerRestrictionsList});
testBtnRules.Add(new Restrictions() { RestrictionId = 2, Description = "Demo2", BlockCode = "AdminBlock2" ,testCustomerRestrictionsList});
return testBtnRules;
}
However I get the error CS0747 Invalid initializer member declarator.
There are two things incorrect with your code that I can see.
Firstly, when you are setting the testCustomerRestrictionsList you do not name the Property that it is being assigned to and this is the compiler error.
Your code should look like:
testBtnRules.Add(new Restrictions() {RestrictionId = 1, Description = "Demo1",BlockCode = "AdminBlock1", CustomerRestrictions = testCustomerRestrictionsList});
In this case I wouldn't worry too much about hardcoding the Restrictions into your unit test. But in the future you may want to look into something like AutoFixture so that you don't need to worry so much about creating your objects.
Secondly, you are not setting up the call to the mock IBtnRulesRepository when the GetRestrictions method is called.
Your test should look like:
[Fact]
public void GetAllBtnRules_Should_Return_All_BtnRules()
{
var repo = new Mock<IBtnRulesRepository>();
var testBtnRules = GetTestBtnRules();
repo.Setup(mock => mock.GetRestrictions())
.Returns(testBtnRules)
.Verifiable();
var controller = new BtnRulesController(repo.Object);
var result = controller.Get();
Assert.Equal(testBtnRules.Count,result.Count);
repo.Verify();
}

How to fill a custom typed List<> from SQL Server

I have a class named Author.cs defined as:
public class Author : Interfaces.INode
{
private List<INode> _targetList;
private List<IAttribute> _attributeObject;
// Author class Constructor
public Author()
{
_targetList = new List<INode>();
}
//implementazion of _TargetObject INode method
public List<INode> _TargetObject
{
get
{
return _targetList;
}
}
//implementazion of _AttributeObject INode method
public List<IAttribute> _AttributeObject
{
get
{
return _attributeObject;
}
}
public int _aID { get; set; }
public string _aName { get; set; }
// 'CoAuthor', 'Venue' and 'Paper' are classes that
// implements an interface i.e. `IAttribute`
public List<CoAuthor> _aCoAuthors { get; set; }
public List<Venue> _aVenue { get; set; }
public List<Paper> _aPapers { get; set; }
public string _aArea { get; set; }
}
which implements an interface in Interfaces folder named Interfaces.INode.cs defined as:
public interface INode
{
List<INode> _TargetObject { get; }
List<IAttribute> _AttributeObject { get; }
}
public interface IAttribute : INode
{}
Now I want to fill a list i.e. List<Author> i.e. is in another class named AuthorCollector.cs
List<Author> _eAthors = new List<Author>();
I have tried as:
try
{
SqlCommand _myCommand_1 = _con.CreateCommand();
_myCommand_1.CommandText = #"SELECT Author_ID FROM M_DataFull
ORDER BY Author_ID, Year";
var _AuthID = 0;
int _Row_Counter = 0;
using (SqlDataReader _myReader_1 = _myCommand_1.ExecuteReader())
{
while (_myReader_1.Read())
{
_Row_Counter++;
_eAthors.Add(Convert.ToInt32(_myReader_1["Author_ID"]));
}
_myReader_1.Close();
}
}
catch(Exception e)
{
Console.WriteLine(e.Message);
}
The error is:
The best overloaded method match for _eAuthors.Add() has some invalid arguments.
using (SqlDataReader _myReader_1 = _myCommand_1.ExecuteReader())
{
while (_myReader_1.Read())
{
_Row_Counter++;
Author author = new Author();
author._aId = Convert.ToInt32(_myReader_1["Author_ID"]);
author._aName = Convert.ToString(_myReader_1["Author_Name"]);
//etc...
_eAthors.Add(author);
}
_myReader_1.Close();
}
you try to add an int to a list of authors. pseudo code:
_eAthors.Add(new Author(Convert.ToInt32(_myReader_1["Author_ID"])));
or
_eAthors.Add(new Author(){_aID =Convert.ToInt32(_myReader_1["Author_ID"]}));
anyway I would use a ORM framework for this like NHibernate or EntityFramework. It's much easier than to do all the SQL Mapping yourself...
_eAthors is a collection of Authors, but the code is trying to add an int value which is causing an error in this case.
Modify this line
_eAthors.Add(Convert.ToInt32(_myReader_1["Author_ID"]))
to
_eAthors.Add(new Author
{
_aid= Convert.ToInt32(_myReader_1["Author_ID"]),
// add additional properties if you have one.
});

Categories

Resources