What's the best solution to implement this? - c#

I'm working with project that will have ONLY one profile that has friends
I allready do that by
static class profile
class friend
profile has static collection of friends
but profile and friend have same variables as name , pic , .. etc
so i decide to make a person abstract class and inherit it
then i found that i can't inherit static class [ profile ] from person as variables will not have properties
so i made variables as static in person
then every friend doesn't have its variables as static variables will belongs to friend class
I'm new to this and i know it's a silly question !!
but what's the best way to implement this
I Preferred Using Static For Profile For Accessibility
I Preferred Using Static Things For Accessibility Purposes

Avoid using static classes. If you want one instance, just create one instance. Static classes make testing difficult.
But going back to design, maybe try introducing a User class:
class User
- name
- picture
- other properties
class Profile
- User myAccountInfo
- List<User> friends

Maybe something like this?:
class User
{
public User(string name, object picture)
{
Name = name;
Picture = picture;
}
public string Name { get; set; }
public object Picture { get; set; } //Change object to a class that holds Picture information.
}
class Profile : User
{
private static Profile _profile;
public List<User> Friends = new List<User>(); //This List<T> can contain instances of (classes that derive from) User.
public Profile(string name, object picture) : base(name, picture) { }
public static Profile GetProfile()
{
return _profile ?? (_profile = new Profile("NameOfProfileHere", null));
}
}

Related

Not able to access protected variables

I have created a simple test project to use a class as a custom List type and have a couple of questions regarding the use of different syntax when declaring variables.
I have a class called CustomerInfo which defines all the variables required to be stored for the customer information which will be added to a list as seen below:
protected string Firstname { get; set; }
protected string Surname { get; set; }
protected int Age
{
get
{
return Age;
}
set
{
if(value < 0)
{
throw new AgeException("Age cannot be a value below 0");
}
else
{
Age = value;
}
}
}
protected string Gender { get; set; }
Questions:
1) Why does the code below not allow me to access the protected variables in the CustomerInfo class even though I am inheriting the class?
class Program : CustomerInfo
{
static void Main(string[] args)
{
CustomerInfo custInfo = new CustomerInfo();
custInfo.Firstname = "Richard"; //not working
custInfo.Surname = "Smith"; //not working
List<CustomerInfo> custList = new List<CustomerInfo>();
custList.Add(custInfo);
}
}
2) When looking at Windows Forms applications they already contain an inheritence of Form in the code of any Form you create. If you have to inherit a class to access the protected variables & methods it has, how can you access the variables if each form already has an inheritance that you cannot remove?
Thanks
You are misunderstanding the purpose of inheritance. Inheritance is designed to represent a relationship between two objects where one is a more specialized version of the other. This is sometimes called an "is-a" relationship.
Consider the following class definitions:
class Fruit {}
class Apple : Fruit {}
class Banana: Fruit {}
In this case, Apple and Banana both inherit from Fruit to express the "is-a" relationship - a Banana is a Fruit. In object-oriented design, this allows you to write a method like this:
class Person
{
public void Eat(Fruit fruit) {}
{
// stuff goes here
}
}
The Eat method allows the Person class to eat anything that is a Fruit, including classes that derive from Fruit. So you can do the following:
Person person = new Person();
Apple apple = new Apple();
Banana banana = new Banana();
person.Eat(apple);
person.Eat(banana);
Compare this to the class definition you have written:
class Program : CustomerInfo
In the language of OOP, this says "a Program is a CustomerInfo." I don't think that's what you want. Using the protected keyword doesn't make sense here because your inheritance relationship doesn't make sense. If Program is supposed to be able to access CustomerInfo members, they should be declared public or internal.
The protected keyword is a member access modifier. A protected member
is accessible within its class and by derived class instances.
Source MSDN
CustomerInfo custInfo = new CustomerInfo();
custInfo.Firstname = "Richard"; //not working
custInfo.Surname = "Smith"; //not working
This code is not working because your custInfo's Firtsname and Surname are not accessible in the Program class. But you should be able to do the following, as your Program class is inherited from CustomerInfo :
Firstname = "Richard";
Surname = "Smith";
For the second question you can do something like the following:
Class1 : Form
{
// here will be your protected members
}
Class2 : Class1

How do I define the signature of a function that must be implemented by instances of a class?

Say I have a class Book:
public class Book{
public string Title {get; set;}
}
I want every book to have a Read function that returns a string and accepts a page number - but the internals will be different for every book (poor example, I know). How do I define the signature of a function that must be implemented by instances of this class?
Something like this:
public class Book{ // need to make this abstract?
public string Title {get; set;}
public abstract string Read(int pageNum);
}
// I want to define instances that define their own behavior...
public static Book It => new Book(){ // can't create instance of abstract...
Title = "It",
Read... // what do I do here?
}
My main concerns are:
Keeping things as simple as possible. Implementing interfaces under abstract classes works, but it gives me n*2 things to worry about as I add more instances.
I will need to add a large number of these custom functions - passing Funcs through constructors seems unwieldy.
In practice - this is used to define a Tenant. The Tenants are defined in-memory, and have many static properties like domain, name, adminEmail, etc. Those are tenant-specific properties... but now I am trying to implement tenant-specific behaviors - like GetBooks or FilterUsers. I would like to keep implementation as simple as humanly possible. Right now I have "If TenantA, do this, else if tenantB, do this..." sprinkled throughout my code. I'm trying to consolidate all tenant-specific logic and detail in one place - on instances of the Tenant class.
Further examples of Tenant specific behavior - you have a SaaS forum software. On the homepage of Forum A, you GetCoverPhoto by reading from a static file. On the homepage of Forum B, you GetCoverPhoto by reading from a blog homepage. Currently, I say "If Forum A, do this, else If Forum B, do this". This is the type of tenant-specific behavior that I want to define on the Tenant object, instead of in code. I don't want any tenant-specific code in my core logic.
Is there a simple feature/pattern in the C# language that will achieve this?
What NineBerry said is very valid.
There is one other way of accomplishing what you might want. If you want to dynamicly inject the read method implementation into a Book. This can be seen as strategy pattern. And can be done as interfaces like in many languages, but in simplest form in C# it can be done by delegates. Example:
public class Book{
Func<int, string> readFunc;
public Book(Func<int, string> readFunc)
{
this.readFunc = readFunc;
}
public string Title {get; set;}
public string Read(int pageNum) { return readFunc(pageNum); }
}
Then use it as:
public static Book It => new Book(){
Title = "It",
Read = (pageNum) => ... // Do actual reading in delegate
}
EDIT: With more detail on requirements (but still not everything is obvious) I would do something like this:
public class Tenant
{
// core things go here
public Extensions Extensions { get; }
}
public class Extensions : IEnumerable<IExtension>
{
private IList<IExtension> list = new List<IExtension();
private Tenant { get; set; }
public Extensions(Tenant tenant)
{
Tenant = tenant;
}
public void Add(IExtension extension)
{
extension.Tenant = Tenant;
list.Add(extension);
}
}
public interface IExtension
{
Tenant { get; set; }
// shared interface of extensions if any can be abstracted
}
public interface ICoverPhotoExtension : IExtension
{
Photo GetCoverPhoto();
}
public class FileCoverPhotoExtension : ICoverPhotoExtension
{
public Tenant { get; set; }
Photo GetCoverPhoto() { } // gets photo from file
}
public class BlogCoverPhotoExtension : ICoverPhotoExtension
{
public Tenant { get; set; }
Photo GetCoverPhoto() { } // gets photo from blog
}
usage:
Tenant tenant; // initialized somehow
var coverPhotoExtension = tenant.Extensions.FirstOrDefault<ICoverPhotoExtension>();
Photo photo = coverPhotoExtension?.GetCoverPhoto();
public Interface IBook{
string Title {get; set;}
func<int,string> ReadPage
}
Use containment over inheritance. In the interface example above there is a function in every book that implements IBook that will return a string for that page.
public class MyBook : IBook{
public Title : {get;set;} = "MyBook";
public func<int,string> ReadPage =(pagenumber)=>{
return GetText(pagenumber);
}
public string GetText(int pageNumber){
//read the page text by number here.
}
}
I would make GetText an extension method similar to this, so each book doesn't need to implement GetText itself.
public static class XBook{
public static string GetText(this IBook book, int pageNumber){
///do the work here and returng string
}
}
To use the Extension method concept:
using XBook;
public class MyBook : IBook{
public Title : {get;set;} = "MyBook";
public func<int,string> ReadPage =(pagenumber)=>{
return this.GetText(pagenumber);
}
}
There are more ways to do this... for now, give it a try.
Having different instances of a class implement functions differently is not possible. Instead, you inherit a new class where you implement the separate behaviour.
public abstract class Book
{
public string Title {get; set;}
public abstract string Read(int pageNum);
}
public class ITBook : Book
{
public override string Read(int pageNum)
{
// Code here
}
}
Then use the class like this:
public static Book It => new ITBook()
{
Title = "It",
}
You could use a property of a delegate type in the Book class to use different functions in different instances of the Book class, but these functions would not have access to the other properties and methods of the instance they would be used by.

Design of API to accept multiple choices in C#?

I have an interface/abstract class where the implementation can support an arbitrary sized dictionary of Name, identifier. Each implementation will have a different format for identifier which is implementation specific.
The caller needs to retrieve the list of Names from the provider and use those to ask the user which he cares about. The user can select one or more.
I considered the following design where the caller gets an array of names and sets the user's choice by passing in an array of ints, identifying the array indicies of the names the user chose.
public abstract String[] GetNames();
public abstract void SetNamesToUse(int[] names);
Not happy with this, I also considered a model where a list of objects would be passed around:
public class NameObject {
public bool SelectedByUser;
public String Name;
private String ProviderSpecificData;
}
...
public abstract List<NameObject> GetNames();
public abstract void SetNamesToUse(List<NameObject> names);
This seems cleaner and easier on the caller.
What other choices do I have? How have you solved similar?
What about this?
interface IIdentifier
{
string Name {get;}
}
abstract class Identifier<T> : IIdentifier
{
private readonly string _name;
private readonly T _id;
public string Name {get;set;}
protected Identifier(string name, T id)
{
_id = id;
_name = name;
}
}
class GuidIdentifier : Identifier<Guid>
{
public GuidIdentifier(string name, Guid identifier)
:base(name, identifier)
{
//?
}
}
class UserOptions
{
private IEnumerable<IIdentifier> _identifiers;
public IEnumerable<IIdentifier> Identifiers {get {return _identifiers;}}
public IIdentifier Selected {get;set;}
public UserOptions(IEnumerable<IIdentifier> identifiers)
{
_identifiers = identifiers;
}
}
I like the consistency of your second example. It has nothing to do with the use of NameObject class or List<>. You can make your first example consistent too:
public abstract String[] GetNames();
public abstract void SetNamesToUse(String[] names);
To select all, you can now simply write
SetNamesToUse(GetNames());
In my experience, a single use case is not enough to choose from the many possible design options. If you write client code for more use cases, however, things start jumping out at you.
In my one-line example above, the GetNames() call looks ambiguous. Is it a call to get the names from the user or a call to get all the available names? A method name change can clarify this:
SetNamesToUse(GetAllNames());
Ferenc Mihaly
http://theamiableapi.com

Class encapsulation with Repository Pattern

I am sortof using a repository pattern to extract information from a database. I have two classes, report and reportRepository.
The trouble I have is that since reportReposity has to fill in all the details for the report object, all the members in the report have to be publicly accessible.
Is there a way so that I can ensure that only the repository class can access some of the methods of the report class and only it can set some of the properties that other classes cannot, sort of like what friend does in c++. Or is there a completely different way of handling this situation?
I am using C# in ASP.NET 2.0
This looks a bit funky but it does what your after, any property with a 'protected' modifier will only be accessable within that class AND any derived classes
public class Person
{
public string Name { get; protected set; }
public int Age { get; protected set; }
}
public class PersonRepository
{
public Person Get()
{
return new PersonBuilder("TestName", 25);
}
private class PersonBuilder : Person
{
public PersonBuilder(string name, int age)
{
this.Name = name;
this.Age = age;
}
}
}
So unless your within the repository you can't see the Person derived class PersonBuilder which has a constructor that populates the protected properties of Person. Externally it looks like your magically populating fields without using setters or constructors.
You can apply access modifiers to properties, e.g:
public string Name { get; internal set; }
Internal gives write access to the specified property for any types in the same assembly.

C# OOPs architecture problem

I am facing a class resolution issue while trying to make my architecture flexible. To make it simple, consider the following example:
I have four tiers: UI, BL, Common and DAL
I have a base class in my BL layer as defined below:
public class User
{
private UserDTO _d;
public User()
{
_d = new UserDTO();
}
public User(UserDTO d)
{
_d = new UserDTO(d);
}
public UserDTO D
{
get { return _d; }
set { _d = value; }
}
//static method (I cannot make it non-static due to some reasons)
public static User GetUser()
{
User user = new User(Provider.DAL.GetUser());
return user;
}
}
The DTO is defined as:
public class UserDTO
{
public int ID;
public UserDTO()
{
}
public UserDTO(UserDTO source)
{
ID = source.ID;
}
}
My DAL is defined as (it returns a DTO not a business object):
public static UserDTO GetUser()
{
UserDTO dto = new UserDTO();
dto.ID = 99;
return dto;
}
Now, I want to "extend" my code so that I can have one more field in my User table: Name. So I create a derived DTO class as:
public class MyUserDTO : UserDTO
{
public string Name;
public MyUserDTO()
{
}
public MyUserDTO(MyUserDTO source)
{
Name = source.Name; //new field
base.ID = source.ID;
}
}
Then, I create a derived User class as:
public class MyUser : User
{
public MyUser()
{
this.D = new MyUserDTO();
}
}
And I create my own custom DAL provider with this method:
public static UserDTO GetUser()
{
UserDTO dto = new MyUserDTO();
dto.ID = 99;
((MyUserDTO)dto).Name = "New Provider Name";
return dto;
}
Now when I access this MyUserDTO object in my BL, it loses resolution:
User.GetUser(DAL.Provider.GetUser())
and in the UI, I dont get the properties in the MyUserDTO.
Is there a method which can help me get those properties in the UI layer, even after I call the static User.GetUser() method (which will in turn call my custom provider returning a MyUserDTO object)?
Thanks,
You don't inherit from a class to add in new data, only inherit if your new class is going to extend the behaviour of your old class.
Give your UserDTO a Name-Value collection to hold its data and populate that. Then you won't have an issue.
You're not getting the derived behaviour because the static method in the user class can't be overriden by the MyUser class.
You should remove the static method (I know you've indicated you can't), but really you should.
Try to extract the creation of your users in another object (factory, repository,...)
As others have mentioned, the problem is with the static method.
I would also suggest using generics or dependency injection to clean up your parallel object hierarchy. You don't want that duplication.
Instead of having a set of almost-identical 'User' and 'MyUser' classes, that have the same hierarchy, just do something like User and plug in the UserDTO type that you want.
If you refactor and remove the object hierarchy duplication, it may make it easier to see a good solution to get around the problem with the static GetUser().
From what I can see it looks like User.GetUser() will return a User object, not a MyUserDTO object, which is why you don't get those extra fields. The DAL layer needs to abide by the contract it was written against. There are a handful of ways you could go about solving this, although some are more "right" than others.
You could cast the object you get out of User.GetUser to the appropriate object which would then give you access to the casted object's fields (assuming the object can be cast to that type). I don't really like this solution from a design perspective, but it would work:
MyDTOUser myDtoUser = User.GetUser() as MyDTOUser;
Other people have posted some other examples of ways around this so I won't repeat those here.

Categories