Most suitable way to access data [closed] - c#

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 7 years ago.
Improve this question
Method 1:
public class1
{
private string _val1;
private string _val2;
public string Value1
{
get {return _val1;}
}
public string Value2
{
get {return _val2;}
}
public void ReadingDataFromDB()
{
//code to retrieve data from database
if(Reader.read())
{
_val1 = reader["val1"].ToString();
_val2 = reader["val2"].ToString();
}
}
}
Method 2:
public class1
{
public void ReadingDataFromDB(out string _val1, out string _val2)
{
_val1 = "";
_val2 = "";
//code to retrieve data from database
if(Reader.read())
{
_val1 = reader["val1"].ToString();
_val2 = reader["val2"].ToString();
}
}
}
In the Method 1 class has properties, but in Method 2 class has a method with output parameters. Both can be used to retrieve data from the database.
I have seen that often Method 1: is used for Business Logic and Method 2 is used for Data Access.
My question is, from the above Method 1 and Method 2 what is the better one for using in data access classes? And are there any specific reasons for that other than personal opinion?

I suggest something like that (Method 1 improved or Method 3):
public class MyClass {
//TODO: find better names for Value1, Value2
public String Value1 {get; private set}
public String Value2 {get; private set}
// static: the method actually creates an instance as read form DB
public static MyClass ReadFromDB() {
//TODO: Create a connection, SQL command here
if (Reader.Read()) {
return new MyClass() {
// Do not forget about NULL
Value1 = reader["val1"].IsDBNull ? null : Convert.ToString(reader["val1"]),
Value2 = reader["val2"].IsDBNull ? null : Convert.ToString(reader["val2"])
}
}
else
return null; // or throw an exception - no data in DB
}
}
...
MyClass test = MyClass.ReadFromDb();
Console.Write(test.Value1);
As for suggestions in the question: Method 2 ruins data incapsulation: it returns two strings when we expect corresponding properties (since we're working with class1); yet another problem is that out's are hard to read. As for Method 1, we usually expect that "ReadingDataFromDB" will read data from the database and return the intance (of class1) that's why I redesign the method into static and add return.

Take a look at an ORM, the EntityFramework for example.
However:
Basicly you should have a Model:
class FooModel {
public string Value1 {get;set;}
public string Value2 {get;set;}
}
And a Repository:
class FooRepository {
private _db;
public FooRepository(SqlConnection db) {
_db = db;
}
public FooModel GetFooModelById(int id) {
//...
var model = new FooModel {
Value1 = reader["val1"].ToString(),
Value2 = reader["val2"].ToString()
};
//...
}
public List<FooModel> GetFooModelCollection() {
//...
}
}
To bring it together:
var connection = new SqlConnection(...);
var repo = new FooRepository(connection);
var myFoo = repo.GetFooModelById(42);

Related

Modify fields in extraneous function

I have a lot of duplicate code places:
if (claimSettingHistoryDto.NewClaimTypeName == claimSettingHistoryDto.OldClaimTypeName)
{
claimSettingHistoryDto.NewClaimTypeName = null;
claimSettingHistoryDto.OldClaimTypeName = null;
}
if (claimSettingHistoryDto.NewApplicantName == claimSettingHistoryDto.OldApplicantName)
{
claimSettingHistoryDto.NewApplicantName = null;
claimSettingHistoryDto.OldApplicantName = null;
}
if (claimSettingHistoryDto.NewDamageSparePartsTotalCostInsertion == claimSettingHistoryDto.OldDamageSparePartsTotalCostInsertion)
{
claimSettingHistoryDto.NewDamageSparePartsTotalCostInsertion = null;
claimSettingHistoryDto.OldDamageSparePartsTotalCostInsertion = null;
}
and so constantly for different classes of different fields
I wish I had a feature like this:
private void SetNull(object newData, object oldData)
{
if (newData == oldData)
{
newData = null;
oldData = null;
}
}
but of course I understand that this is not true, since I only change the local value inside the function. How do I change the class field?
There are multiple ways of doing that, with varying positions on the "good idea" to "bad idea" spectrum.
Fields as ref parameters (good idea)
(...) this is not true, since I only change the local value inside the function
You're wrong, because ref and out parameters allow you to change values non-locally.
If you have access to the actual fields, you can pass them as a ref parameter:
public class Dto
{
private string? _old;
private string? _new;
public string? Old => _old;
public string? New => _new;
public void Foo() {
SetNullIfEqual(ref _new, ref _old);
}
private static void SetNullIfEqual<T>(ref T? newData, ref T? oldData) where T: class
{
if (newData == oldData)
{
newData = null;
oldData = null;
}
}
}
More info on passing as reference here.
This won't work with properties, even if they have a default setter. Properties are not fields, they're methods in disguise. If you can't access the actual fields...
Properties as delegates (meh idea)
... having access to properties only you'd need to pass them as delegates like this:
public class Dto
{
public string? Old { get; set; }
public string? New { get; set; }
}
public class Outside
{
public void Foo(Dto dto) {
SetNullIfEqual(() => dto.New, () => dto.Old, v => dto.New = v, v => dto.Old = v);
}
private static void SetNullIfEqual<T>(
Func<T?> getNew,
Func<T?> getOld,
Action<T?> setNew,
Action<T?> setOld) where T: class
{
if (getNew() == getOld())
{
setNew(null);
setOld(null);
}
}
}
This is clunky though, you have to question how much space it'd actually save. An instance method working on fields as in the first suggestion works much better.
When you have reflection everything looks like a nail (probably bad idea)
You can also do this with reflection, which will remove all safety, give much worse performance, but the absolute most flexibility.
using System.Reflection;
public class Dto
{
public string? Old { get; set; }
public string? New { get; set; }
}
public class Outside
{
public void Foo(Dto dto) {
SetNullIfEqual(nameof(dto.New), nameof(dto.Old), dto);
}
private static void SetNullIfEqual<T>(
string newPropName,
string oldPropName,
T instance)
{
PropertyInfo newProp = typeof(T).GetProperty(newPropName);
PropertyInfo oldProp = typeof(T).GetProperty(oldPropName);
if (Equals(newProp.GetValue(instance), oldProp.GetValue(instance)))
{
newProp.SetValue(instance, null);
oldProp.SetValue(instance, null);
}
}
}
I removed all error handling for brevity.
Recommendation
I'd go with the fields-as-ref-parameters way. If the method in question lives outside of the type, so it can't have access to the fields (don't ever use public fields please), I'd just move it into the type. In your case it'd be a bunch of methods called SetClaimTypeName, SetApplicantName, etc.

How to get single object from an api and display it [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 1 year ago.
Improve this question
I am trying to build an app that helps you make dinner decisions. I want the user to be able to click a button and the app should display one random dinner name using an API. I am trying to display the data from an API. This is my code so far. I am getting a null exception. Any assistance is appreciated :)
namespace jello
{
public partial class NetworkingManager : ContentPage
{
private string name;
public string url;
public String Name {
get { return name; }
set
{
name = value;
}
}
public class RecipeClass
{
public class Data
{
public string strMeal { get; set; }
}
public Data data { get; set; }
}
public const string Url = "https://www.themealdb.com/api/json/v1/1/search.php?f=a";
public HttpClient client = new HttpClient();
public NetworkingManager()
{
InitializeComponent();
BindingContext = this;
name = GetDetails();
}
string temp;
public async void GetString()
{
var content = await client.GetStringAsync(Url);
temp = content;
}
public RecipeClass getObj()
{
var output = JsonConvert.DeserializeObject<RecipeClass>(temp);
return output;
}
public String GetDetails()
{
var name = getObj().data.strMeal;
return name;
}
}
}
Your underlying problem is that you want to call something asynchronous from your constructor and constructors cannot be async. You can solve that by using this asynchronous factory pattern:
First make your constructor private so it cannot be called from the outside:
private NetworkingManager()
{
InitializeComponent();
BindingContext = this;
}
Then you make an async method to initialize it:
private async Task<MyClass> InitializeAsync()
{
var temp = await GetStringAsync();
var output = JsonConvert.DeserializeObject<RecipeClass>(temp);
name = output.data.strMeal;
return this;
}
public async Task<string> GetStringAsync()
{
return await client.GetStringAsync(Url);
}
And finally an async method to create it:
public static Task<NetworkingManager> CreateAsync()
{
var manager = new NetworkingManager();
return manager.InitializeAsync();
}
You construct the instance from the outside by doing:
NetworkingManager instance = await NetworkingManager.CreateAsync();
And finally a note about naming: Don't call a class member temp. There's nothing temporary about it. It lives as long as the instance. Don't call a method the very general GetString if it gets a specific string like here. Call it GetMealString or GetMealName or something. The same goes for getObj, which should start with a capital letter by the way. Name your mebers in a clear and specific way and the program's structure will become much clearer to you.
You can do this :
public async void GetMeal()
{
var content = await client.GetStringAsync(Url);
var output = JsonConvert.DeserializeObject<RecipeClass>(content);
Name = output.data.strMeal;
}
And call it like this :GetMeal() you don't need to put name = GetMeal(); Your property
Name is set at the end.

Generate a strongly-typed proxy that can track changes on property names not values when one property is set to another

Setup:
public class Data
{
public int A { get; set; }
public int B { get; set; }
}
public class Runner
{
public static void Run(Data data)
{
data.A = data.B;
data.A = 1;
}
}
class Program
{
static void Main(string[] args)
{
var data = new Data() { A = 1, B = 2 };
Runner.Run(data);
}
}
Problem: I need to implement change tracking here for property names not values. Inside Runner.Run on the first line data.A = data.B I need to record somehow that "A" was set to "B" (literally property names) and then on the next line data.A = 1 I need to record that "A" was set to constant and say forget about it.
Constrains:
When setting one property to another (e.g. A = B) that needs to be recorded
When setting property to anything else (e.g. A = 1 or A = B * 2) this change needs to be forgotten (e.g. remember A only)
Suppose this is the tracker contract being used:
void RecordChange(string setterName, string getterName);
void UnTrackChange(string setterName);
Question:
I would like to somehow proxy the Data class so it still can be used in the interface code (e.g. Runner - is a whole bunch of a business logic code that uses Data) INCLUDING strong-typing and it can track it's changes without modifying the code (e.g. there is lots of places like 'data.A = data.B').
Is there any way to do it without resorting to I guess some magic involving IL generation?
Already investigated/tried:
PostSharp interceptors/Castle.DynamicProxy with interceptors - these alone cannot help. The most I can get out of it is to have a value of data.B inside setter interceptor but not nameof(data.B).
Compiler services - haven't found anything suitable here - getting the name of caller doesn't really help.
Runtine code generation - smth like proxy inherited from DynamicObject or using Relfection.Emit (TypeBuilder probably) - I lose typings.
Current solution:
Use the Tracker implementation of the abovementioned contract and pass it around into every function down the road. Then instead of writing data.A = data.B use method tracker.SetFrom(x => x.A, x => x.B) - tracker holds a Data instance and so this works. BUT in a real codebase it is easy to miss something and it just makes it way less readable.
It is the closest the solution I've come up with. It isn't perfect as I still need to modify all the contracts/methods in the client code to use a new data model but at least all the logic stays the same.
So I'm open for other answers.
Here's the renewed Data model:
public readonly struct NamedProperty<TValue>
{
public NamedProperty(string name, TValue value)
{
Name = name;
Value = value;
}
public string Name { get; }
public TValue Value { get; }
public static implicit operator TValue (NamedProperty<TValue> obj)
=> obj.Value;
public static implicit operator NamedProperty<TValue>(TValue value)
=> new NamedProperty<TValue>(null, value);
}
public interface ISelfTracker<T>
where T : class, ISelfTracker<T>
{
Tracker<T> Tracker { get; set; }
}
public class NamedData : ISelfTracker<NamedData>
{
public virtual NamedProperty<int> A { get; set; }
public virtual NamedProperty<int> B { get; set; }
public Tracker<NamedData> Tracker { get; set; }
}
Basically I've copy-pasted the original Data model but changed all its properties to be aware of their names.
Then the tracker itself:
public class Tracker<T>
where T : class, ISelfTracker<T>
{
public T Instance { get; }
public T Proxy { get; }
public Tracker(T instance)
{
Instance = instance;
Proxy = new ProxyGenerator().CreateClassProxyWithTarget<T>(Instance, new TrackingNamedProxyInterceptor<T>(this));
Proxy.Tracker = this;
}
public void RecordChange(string setterName, string getterName)
{
}
public void UnTrackChange(string setterName)
{
}
}
The interceptor for Castle.DynamicProxy:
public class TrackingNamedProxyInterceptor<T> : IInterceptor
where T : class, ISelfTracker<T>
{
private const string SetterPrefix = "set_";
private const string GetterPrefix = "get_";
private readonly Tracker<T> _tracker;
public TrackingNamedProxyInterceptor(Tracker<T> proxy)
{
_tracker = proxy;
}
public void Intercept(IInvocation invocation)
{
if (IsSetMethod(invocation.Method))
{
string propertyName = GetPropertyName(invocation.Method);
dynamic value = invocation.Arguments[0];
var propertyType = value.GetType();
if (IsOfGenericType(propertyType, typeof(NamedProperty<>)))
{
if (value.Name == null)
{
_tracker.UnTrackChange(propertyName);
}
else
{
_tracker.RecordChange(propertyName, value.Name);
}
var args = new[] { propertyName, value.Value };
invocation.Arguments[0] = Activator.CreateInstance(propertyType, args);
}
}
invocation.Proceed();
}
private string GetPropertyName(MethodInfo method)
=> method.Name.Replace(SetterPrefix, string.Empty).Replace(GetterPrefix, string.Empty);
private bool IsSetMethod(MethodInfo method)
=> method.IsSpecialName && method.Name.StartsWith(SetterPrefix);
private bool IsOfGenericType(Type type, Type openGenericType)
=> type.IsGenericType && type.GetGenericTypeDefinition() == openGenericType;
}
And the modified entry point:
static void Main(string[] args)
{
var data = new Data() { A = 1, B = 2 };
NamedData namedData = Map(data);
var proxy = new Tracker<NamedData>(namedData).Proxy;
Runner.Run(proxy);
Console.ReadLine();
}
The Map() function actually maps Data to NamedData filling in property names.

Method Inference of Type T

Question
How do I define an incoming Type T constraint that will allow me to call a static method on the class (of type T) to get the intended IndexModel object for passing to Mongo?
Background
I'm currently trying to write a Mongo Provider class that will allow me to ensure my particular database and collection are present before doing any operations with them, since there is a potential that the container or server it resides in could be destroyed and recreated at any time, and I'd prefer to have a safe way in code to ensure that the external dependency is there (instance is beyond my control, so I have to trust that something is there).
One of the things I'm trying to do, since I've managed to do what I stated above for Database and Collection instantiation, is to also generate indexes. My idea was to have a static method on the classes that would return their specific definition of an index model. This way, each class would be responsible for their own Mongo indexes, rather than some convoluted switch-case statement in my Provider based on the incoming type of T.
My first idea was to have an interface that shared this method, but Interfaces don't allow you to declare a static method. Similarly, I tried an Abstract Base-class and found that the static implementation would call the base class that defined the method, rather than any overrides in an inheritor.
Sample Code
public class MyClass
{
public DateTime DateValue { get; set; }
public int GroupId { get; set; }
public string DataType { get; set; }
public static IEnumerable<CreateIndexModel<MyClass>> GetIndexModel(IndexKeysDefinitionBuilder<MyClass> builder)
{
yield return new CreateIndexModel<MyClass>(
builder.Combine(
builder.Descending(entry => entry.DateValue),
builder.Ascending(entry => entry.GroupId),
builder.Ascending(entry => entry.DataType)
)
);
}
}
Edit
I guess I should probably include a shell of my Mongo Provider class. See below:
Edit #2 due to questions about how this hasn't solved my problem, I'm updating the MongoProvider to have the problematic code. Note: Once this method is included, the class will no longer compile, since it isn't possible given what I've done thus far.
public class MongoProvider
{
private readonly IMongoClient _client;
private MongoPrivder(ILookup<string, string> lookup, IMongoClient client)
{
_client = client;
foreach(var database in lookup)
foreach(var collection in database)
Initialize(database.Key, collection);
}
public MongoProvider(IConfiguration config) :this(config.GetMongoObjects(), config.GetMongoClient())
{}
public MongoProvider(IConfiguration config, IMongoClient client) : this(config.GetMongoObjects(), client)
{}
private void Initialize(string database, string collection)
{
var db = _client.GetDatabase(database);
if (!db.ListCollectionNames().ToList().Any(name => name.Equals(collection)))
db.CreateCollection(collection);
}
// The Problem
private void InitializeIndex<T>(string database, string collection)
{
IEnumerable<CreateIndexModel<T>> models;
switch (T)
{
case MyClass:
model = MyClass.GetIndexModel();
break;
default:
break;
}
await _client.GetDatabase(database)
.GetCollection<T>(collection)
.Indexes
.CreateManyAsync(models);
}
}
Edit #3
As a stop-gap, I've gone ahead and done something terrible (not sure if it's going to work yet), and I'll supply the example so you can know my best solution thus far.
public static class Extensions
{
#region Object Methods
public static T TryCallMethod<T>(this object obj, string methodName, params object[] args) where T : class
{
var method = obj.GetType().GetMethod(methodName);
if (method != null)
{
return method.Invoke(obj, args) as T;
}
return default;
}
#endregion
}
This allows me to do the following (inside of MongoProvider)
private async void InitializeIndex<T>(string database, string collection) where T : new()
{
var models = new T().TryCallMethod<IEnumerable<CreateIndexModel<T>>>("GetIndexModel");
await _client.GetDatabase(database)
.GetCollection<T>(collection)
.Indexes
.CreateManyAsync(models);
}
Since it doesn't look like I'm going to get an answer to this, I figured I would provide my solution for future searches of this question. Basically, I added an extension method to the base object class, and used reflection to determine if the method I was looking for was there. From there, I returned a value of true or false, depending on if the method was found, and output the return value to a parameter, in the traditional TryGet pattern.
Note to Future Readers
I do not recommend this approach. This is just how I solved my problem for accessing a method on a type of T. Ideally, an instance method would be implemented, and a signature defined in a common Interface, but that wasn't going to work for my use case.
My Answer
public static class Extensions
{
#region Object Methods
public static bool TryCallMethod<T>(this object obj, string methodName, out T result, params object[] args) where T : class
{
result = null;
var method = obj.GetType().GetMethod(methodName);
if (method == null)
return false;
result = method.Invoke(obj, args) as T;
return true;
}
#endregion
}
My data class looks like this (obfuscated from actual usage)
[BsonDiscriminator("data")]
public class DataClass
{
#region Private Fields
private const string MongoCollectionName = "Data";
#endregion
#region Public Properties
public string CollectionName => MongoCollectionName;
[BsonId]
public ObjectId Id { get; set; }
[BsonElement("date_value")]
public DateTime DateValue { get; set; }
[BsonElement("group_id")]
public int GroupId { get; set; }
[BsonElement("data_type")]
public string DataType { get; set; }
[BsonElement("summary_count")]
public long SummaryCount { get; set; }
[BsonElement("flagged_count")]
public long FlaggedCount { get; set; }
[BsonElement("error_count")]
public long ErrorCount { get; set; }
#endregion
#region Constructor
public DataClass()
{
}
public DataClass(int groupId, string dataType = null, long summaryCount = 0, long flaggedCount = 0, long errorCount = 0)
{
Id = ObjectId.GenerateNewId();
DateValue = DateTime.UtcNow;
GroupId = groupId;
DocCount = summaryCount;
DataType = dataType ?? "default_name";
FlaggedCount = flaggedCount;
ErrorCount = errorCount;
}
#endregion
#region Public Methods
public static IEnumerable<CreateIndexModel<AuditEntry>> GetIndexModel(IndexKeysDefinitionBuilder<AuditEntry> builder)
{
yield return new CreateIndexModel<AuditEntry>(
builder.Combine(
builder.Descending(entry => entry.DateValue),
builder.Ascending(entry => entry.GroupId),
builder.Ascending(entry => entry.DataType)
)
);
}
#endregion
}
I would then call the method in the following fashion, inside my MongoProvider class. The ellipses are present to identify that more code exists within the class.
public class MongoProvider : IMongoProvider
{
#region Private Fields
private readonly IMongoClient _client;
#endregion
#region Constructor
...
#endregion
#region Private Methods
private void Initialize(string database, string collection)
{
var db = _client.GetDatabase(database);
if (!db.ListCollectionNames().ToList().Any(name => name.Equals(collection)))
db.CreateCollection(collection);
}
private async Task InitializeIndex<T>(string database, string collection) where T : new()
{
if(new T().TryCallMethod<IEnumerable<CreateIndexModel<T>>>("GetIndexModel", out var models, new IndexKeysDefinitionBuilder<T>()))
await _client.GetDatabase(database)
.GetCollection<T>(collection)
.Indexes
.CreateManyAsync(models);
}
private static void ValidateOptions<T>(ref FindOptions<T, T> options)
{
if(options != null)
return;
options = new FindOptions<T, T>
{
AllowPartialResults = null,
BatchSize = null,
Collation = null,
Comment = "AspNetWebService",
CursorType = CursorType.NonTailable,
MaxAwaitTime = TimeSpan.FromSeconds(10),
MaxTime = TimeSpan.FromSeconds(10),
Modifiers = null,
NoCursorTimeout = false,
OplogReplay = null
};
}
private static FilterDefinition<T> GetFilterDefinition<T>(Func<FilterDefinitionBuilder<T>, FilterDefinition<T>>[] builders)
{
if(builders.Length == 0)
builders = new Func<FilterDefinitionBuilder<T>, FilterDefinition<T>>[] {b => b.Empty};
return new FilterDefinitionBuilder<T>()
.And(builders
.Select(b => b(new FilterDefinitionBuilder<T>()))
);
}
#endregion
#region Public Methods
public async Task<IReadOnlyCollection<T>> SelectManyAsync<T>(string database, string collection, FindOptions<T, T> options = null, params Func<FilterDefinitionBuilder<T>, FilterDefinition<T>>[] builders) where T : new()
{
ValidateOptions(ref options);
await InitializeIndex<T>(database, collection);
var filter = GetFilterDefinition(builders);
var find = await _client.GetDatabase(database)
.GetCollection<T>(collection)
.FindAsync(filter, options);
return await find.ToListAsync();
}
...
#endregion
}

Is this a valid code for factory method pattern please verify [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 8 years ago.
Improve this question
Code below is for factory method pattern I would like it to be verified. if not valid then what are the changes that need to be made.
here i have added both client code from where the pattern is made use and the code for implementation of pattern.
the example i have used here is of TV remote which acts as factory and returns me TV channel object based on the channel number.
client code
private void button3_Click(object sender, EventArgs e)
{
ITVChannelNew channelNew;
channelNew = RemoteNew.getChannel(1);
currentProgram = channelNew.getCurrentShow();
channelNew = RemoteNew.getChannel(2);
currentProgram = channelNew.getCurrentShow();
}
Factory method code
namespace WindowsFormsApplication1
{
public interface ITVChannelNew
{
string getCurrentShow();
string getNextShow();
string getPreviousShow();
}
public class TVChannelNew : ITVChannelNew
{
private readonly string previous;
private readonly string current;
private readonly string next;
public TVChannelNew(string previous, string current, string next)
{
this.previous = previous;
this.current = current;
this.next = next;
}
public string getCurrentShow()
{
return current;
}
public string getNextShow()
{
return next;
}
public string getPreviousShow()
{
return previous;
}
}
public class BBCNew : TVChannelNew
{
public BBCNew():base("BBC previous","BBC current","BB next")
{
}
}
public class TimesNowNew : TVChannelNew
{
public TimesNowNew()
: base("TimesNow previous", "TimesNow current", "TimesNow next")
{
}
}
public static class RemoteNew
{
public static ITVChannelNew getChannel(int ChannelNumber)
{
switch (ChannelNumber)
{
case 1:
return new BBCNew();
case 2:
return new TimesNowNew();
default:
return new TimesNowNew();
}
}
}
}
Yes that looks good to me.
But for me I would want to have a clearer indication of what type I would expect on the client level. To do this I would define a enum somewhere such as:
public enum TVChannels
{
BBCNew,
TimesNowNew
}
And define the Factory like:
public static class RemoteNew
{
public static ITVChannelNew getChannel(TVChannels channel)
{
switch (channel)
{
case TVChannels.BBCNew:
break;
case TVChannels.TimesNowNew:
break;
default:
break;
}
}
}
This way you have clearer indication what type you want to return and also still leaves the client without knowing any of the concrete types, such as:
private void button3_Click(object sender, EventArgs e)
{
ITVChannelNew channelNew;
channelNew = RemoteNew.getChannel(TVChannels.BBCNew);
currentProgram = channelNew.getCurrentShow();
channelNew = RemoteNew.getChannel(TVChannels.TimesNowNew);
currentProgram = channelNew.getCurrentShow();
}
Also, if someone changed the numbers around in your factory (in the switch statement), it is not immediately clear that it is wrong. If he did spot something wrong he/she will have to ask 'what is channel 45 again?' or 'what is channel 3 meant to return?' and probably have to check some other source to check the correct values.
If you use the enumerations and someone swapped it around accidentally, the next person will stand a better chance in spotting a mistake due to the obvious wording.
Yes the factory looks fine too me, I would perhaps call the factory TVChannelNewFactory but otherwise it seems fine.

Categories