I use Windows Communication Services (WCF) in my project.
In my project,
I write the function like below:
GetUserNameByUserId(int userId);
GetProductInformationByProductId(int productId);
But this naming have been coming more and more complex day by day.
For instance I have 5 parameters to pass to the function, in this case the function name will be like blow:
GetStackOverFlowByStackByOverByFlowByIdByStackOverFlow(string stack, string over, string flow, int id, string stackOverFlow);
And assume that I want to get with 2 parameters like blow:
GetStackOverFlowByIdByStackOverFlow(int id, string stackOverFlow);
I want to use function overloading like below:
public void abc(int i)
{
System.Console.WriteLine("abc" + i);
}
public void abc(string i)
{
System.Console.WriteLine("abc" + i);
}
public void abc(string i,int j)
{
System.Console.WriteLine("abc" + i + j);
}
That is to say, I want to write below functions:
GetStackOverFlow(int id);
GetStackOverFlow(int id, string name);
GetStackOverFlow(int id, string name, string StackOver);
.
.
Isn't it?
Are there any methodology for that?
Or am I doing right?
I research and find this:
Function Overloading in WCF
public interface IMyService
{
[OperationContract(Name = "GetStringWithParam")]
string GetString(DateTime date);
[OperationContract(Name = "GetStringWithoutParam")]
string GetString();
}
and he said that
But i don't prefer it as it is sometimes lead to confusion.
are there any other way?
Thanks.
You could use a class as a parameter.
[DataContract]
public class MySearchSettings
{
[DataMember]
public int? ID { get; set; }
[DataMember]
public string Name { get; set; }
[DataMember]
public string StackOver { get; set; }
}
and than create a method like this:
public GetStackOverflowResponse GetStackOverflow(MySearchSettings searchSettings)
{
var response = new GetStackOverflowResponse();
try
{
User user = null;
if (searchSettings == null)
throw new ArgumentNullException("searchSettings");
if (searchSettings.ID.HasValue)
user = //queryByID;
else if (!String.IsNullOrEmpty(searchSettings.Name))
user = //queryByName;
else if (!String.IsNullOrEmpty(searchSettings.StackOver))
user = //queryByStackOver;
response.User = user;
}
catch(Exception e)
{
response.ErrorMessage = String.Format("{0}: {1}",
e.GetType().Name,
e.Message);
}
return response;
}
I have not included the GetStackOverflowResponse class but you get the idea of it.
One of the benefits of this is that you could easily extend the class without breaking functionality of a client when a newer version of your Service is deployed.
You are doing fine and this is how you overload methods in WCF(using the name property).I dont see a better approach than using the name property to overload methods.
Related
I created a function that add a new user with Angular/WebAPI , so in angular i send the object like this :
AddUser(person : person):Observable<person>
{
return this.http.post<person>(this.baseUrl,person);
}
and in WebAPI i got the data :
[HttpPost]
public async Task<ActionResult<Person>> PostPerson(Person person)
{
Now I want to add a picture of each user, and i don't know how it's gonna be the objet in angular, should i add a property imageProfile as File which i'm not sure if it's possible , or it should be a string of the uploaded file.
export class person {
idPerson:number=0;
fname : string ="" ;
lname : string ="";
password : string ="";
idCategory? :number;
nameCategory:string="";
imageProfile :
}
That's very good info from Codemaze, as always. The remark from Lavstsen is not correct, there's no need for a separate call.
For example, you could have a form linked to the structure of the person-type:
initializeForm() {
this.personForm = this.form.group({
fname: [''],
})
}
In your onSubmit-method, you seize the date from your form and put in a dto, in this example through a getPersonDto-method
private getPersonDto(): PersonDto {
let dto = new PersonDto();
dto.fname = this.imageForm.controls.fname.value;
return dto;
}
and next you can solve it like this:
const formData = new FormData();
formData.append('Imagefile', this.selectedFile, this.selectedFile.name);
formData.append('fname', personDto.fname); // needs to be strings => toString()
this.personApiClient.uploadImageFile(this.personId, formData)
.subscribe((res: any) => {
this.uploadOrDeleteResults = res;
this.showToastrMessageSuccess("PAGES.COMMON.TOASTR.TITLE.SUCCESSFULCREATE", "PAGES.COMMON.TOASTR.MESSAGE.SUCCESSFULCREATE");
},
(error) => {
this.crudHasErrors = true;
this.errorHttpErrorResponse = error;
this.errors = this.errorHttpErrorResponse.error;
},
you don't need the dto-step as such, but if you structurally always use dto's in your application, it would make more sense
Take care and good luck
I have another workaround but this will only work for very small files where you don't need upload percentage to show on UI.
I have my controller like this:
[HttpPost("/api/sign-up")]
public void SaveUser([FromForm] UserModel info)
{
_logger.LogDebug(null, "Hello", info); // Just to see contents of info object in debugger
}
and make your model like this:
public class UserModel
{
[FromForm(Name = "avatar")]
public IFormFile Avatar { get; set; }
[FromForm(Name = "email")]
public string Email { get; set; }
}
With "Best Way" I mean, maybe, without many If, clean code.
I have a function that receives as parameters (string currentVersion, string action)
and it should return a string versionToBe = "";
For action = "installOldVersion"
-------------if "currentVersion"----------------: -------------OldversionToInstall--------------
"windows10(pro)", "windows10(pro)(education)" : "windows81(pro)"
"windows10(enterprise)", "windows10(enterpise)(lstb)" : "windows81(enterprise)"
"windows7(home)", "windows7(home)(basic)", "windows7(basic)", "windows7": "windowsVista(starter)"
"windowsXP(starter)", "windowsXP(starter)(home)", "windowsXP(home)", "windowsXP": "windows2000(professional)"
"windowsNT(workstation)", "windowsNT": "windows95(sp1)"
For action = "installNewVersion"
-------------if "currentVersion"----------------: -------------NewVersionToInstall--------------
"windows81(pro)", "windows81(pro)(education)" : "windows10(pro)"
"windows81(enterprise)", "windows81(enterprise)(education)" : "windows10(enterprise)"
"windowsVista(starter)", "windowsVista(starter)(package)", "windowsVista(package)", "windowsVista": "windows7(home)"
"windowsVista(starter)", "windowsVista(starter)(praok)", "windowsVista(praok)", "windowsVista": "windowsXP(starter)"
"windows95(sp1)", "windows95(sp1)(versionE)", "windows95": "windowsNT(workstation)"
So,for example, everytime the string name comes like: "windows10(pro)" or "windows10(pro)(education)" it should return: "windows81(pro)".
I know this can get done with lots of if like:
if (version.Equals("windows10(pro)") || version.Equals("windows10(pro)(education)"))
{
versionToBe = "windows81(pro)";
}
and the same for the rest of them, anding with 10 If statements in Total.
But If there's a better way to do it, I'd want to know.
Another restriction, or other thing to consider:
if the action is "installOldVersion", versionToBe is OldversionToInstall,
and if the action is "installNewVersion", versionTobe would be NewVersionToInstall.
You could create a list of objects with CurrentVersion, Old Version and New Version and then extract the one you want from the list.
Example Instruction Class Definition
public class VersionInformation
{
public string CurrentVersion {get; set;}
public string NewVersion {get; set;}
public string OldVersion {get; set;}
}
then in your program, have a list of them, either hard coded or loaded from file or whatever datastore you want and do your version check as follows:
private List<VersionInformation> _versionInformation = //Load your list from wherever;
public void DoVersionCheck(string version)
{
var currentversionInfo = _versionInformation.Single(x=> x.CurrentVersion == version);
//Do Whatever you want with the upgrades and downgrades here based on whatever action you are doing
}
Set yourself up a dictionary and perform a lookup.
As an exercise for the reader:
You could drive the dictionary contents from some configuration or other...even from a database if you want.
You'd presumably want to set up your dictionary as a static and initialize it only once.
You'll want some handling for when there is no dictionary entry - you don't specify a default in your question.
Dictionary, string> ActionMatrix = new Dictionary, string>();
ActionMatrix.Add(Tuple.Create ("windows10(pro)", "installOldVersion"), "windows81(pro)");
ActionMatrix.Add(Tuple.Create ("windows10(pro)(education)", "installOldVersion"), "windows81(pro)");
ActionMatrix.Add(Tuple.Create ("windows10(enterprise)", "installOldVersion"), "windows81(enterprise)");
ActionMatrix.Add(Tuple.Create ("windows10(enterpise)(lstb)", "installOldVersion"), "windows81(enterprise)");
// etc
ActionMatrix.Add(Tuple.Create("windows81(pro)", "installNewVersion"), "windows10(pro)");
ActionMatrix.Add(Tuple.Create("windows81(pro)(education)", "installNewVersion"), "windows10(pro)");
ActionMatrix.Add(Tuple.Create("windows81(enterprise)", "installNewVersion"), "windows10(enterprise)");
ActionMatrix.Add(Tuple.Create("windows10(enterpise)(education)", "installNewVersion"), "windows10(enterprise)");
// etc
public string VersionToBe (string currentVersion, string action)
{
return ActionMatrix[Tuple.Create(currentVersion, action)];
}
A simple object with it's own list should do the trick and is visually better to follow.
public class VersionData
{
private static List<VersionData> VersionDatas { get; set; } = new List<VersionData>()
{
new VersionData( "OldversionToInstall", new [] {"windows10(pro)", "windows10(pro)(education)" }.ToList(), "windows81(pro)" ),
new VersionData( "OldversionToInstall", new [] {"windows10(enterprise)", "windows10(enterpise)(lstb)" }.ToList(), "windows81(enterprise)" )
};
public string Action { get; set; } = "";
public List<string> CurrentVersions { get; set; } = new List<string>();
public string Version { get; set; } = "";
public VersionData(string action, List<string> currentVersions, string version)
{
Action = action;
CurrentVersions = currentVersions;
Version = version;
}
public static string GetVersion(string action, string currentVersion)
{
return VersionDatas.FirstOrDefault(o => o.Action == action && o.CurrentVersions.Any(x => x == currentVersion)).Version;
}
}
and to call it's as simple as :
var oldVersion = VersionData.GetVersion("OldversionToInstall", "windows10(enterpise)(lstb)");
I'm trying to create a method which can be used like this:
Assembler.CreateTransfer(i);
i is an item inside a dynamic collection.
i is a domain object.
CreateTransfer() should return an instance of i type + Transfer (if my domain object is User, then it should return an instance of UserTransfer.
As for my models is like this:
public abstract class UserBase {
public long UserId { get; set; }
public string Username { get; set; }
}
public class UserTransfer : UserBase, ITransferObject { }
public partial class User : UserTransfer, IModelBase, IDomainObject {
public User() {
Roles = new List<Role>();
}
public virtual ICollection<Role> Roles { get; set; }
}
So far, I've accomplished this:
public static TTransfer CreateTransfer<TTransfer, TDomain>(TDomain d)
where TTransfer : ITransferObject
where TDomain : IDomainObject
{ ... }
This works, because I know the type of TTransfer and TDomain.
And I can call it like: CreateTransfer<UserTransfer, User>(d).
The problem comes when I try create the dto without specifying any type:
CreateTransfer(d);
Of course I've added an overload for this task and I hope I can magically accomplish the following:
public static ITransferObject CreateTransfer(IDomainObject d) {
// do magic
return CreateTransfer<transfer, domain>(d);
}
But in the real world, this is as far as I could get:
public static ITransferObject CreateTransfer(IDomainObject d) {
var dType = d.GetType();
var assemblyName = dType.Assembly.FullName;
var domainName = dType.FullName;
var transferName = domainName + "Transfer";
var domain = Activator.CreateInstance(assemblyName, domainName).UnWrap();
var transfer = Activator.CreateInstance(assemblyName, transferName).UnWrap();
return CreateTransfer< ?, ?>(d); // Problem
}
Both domain and transfer objects are being created correctly.
The main question is: Is there any way to be able to call CreateTransfer<domain, transfer>(d)? Any help will be appreciated.
You can use reflection to call the generic method.
Something like this:
var method = typeof(ClassThatDefinesCreateTransfer)
.GetMethods()
.Single(x => x.Name == "CreateTransfer" &&
x.IsGenericMethodDefinition)
.MakeGenericMethod(dType, transferType);
return (ITransferObject )method.Invoke(null, new object[] { d });
You probably want to cache at least the result of typeof(ClassThatDefinesCreateTransfer).GetMethods().
I have a multiple layered application I'm rewriting using Entity Framework 4 w/ Code First. The important things:
In the data layer, on my context, I have:
public DbSet<MobileSerialContainer> Mobiles { get; set; }
This context has a static instance. I know, I know, terrible practice. There are reasons which aren't relevant to this post as to why I'm doing this.
MobileSerialContainer consists of the following:
[Table("Mobiles")]
public sealed class MobileSerialContainer
{
[Key]
public long Serial { get; set; }
[StringLength(32)]
public string Name { get; set; }
public MobileSerialContainer() { }
public MobileSerialContainer(Mobile mobile)
{
Mobile = mobile;
LeContext.Instance.Mobiles.Add(this);
}
[StringLength(1024)]
public string FullClassName
{
get { return Mobile == null ? "" : Mobile.GetType().AssemblyQualifiedName; }
set
{
if (string.IsNullOrEmpty(value) || value == FullClassName)
return;
Mobile = null;
var type = Type.GetType(value);
if (type == null)
return;
if (!type.IsSubclassOf(typeof(Mobile))
&& type != typeof(Mobile))
return;
var constructor = type.GetConstructor(new [] { GetType() });
// The problem here is that Person ( which extends mobile ) does not have a constructor that takes a MobileSerialContainer.
// This is a problem of course, because I want to make this entire layer transparent to the system, so that each derivative
// of Mobile does not have to implement this second constructor. Blasphemy!
if (constructor == null)
return;
Mobile = (Mobile)constructor.Invoke(new object[] { this });
}
}
public string SerializedString
{
get
{
return Mobile == null ? "" : Mobile.Serialize();
}
set
{
if (Mobile == null)
return;
if (string.IsNullOrEmpty(value))
return;
Mobile.Deserialize(value);
}
}
[NotMapped]
public Mobile Mobile { get; set; }
public void Delete()
{
LeContext.Instance.Mobiles.Remove(this);
}
}
Now... I know this is a long post bear with me. Mobile is this:
public class Mobile
{
public long Serial { get { return Container.Serial; } }
public string Name { get { return Container.Name; } set { Container.Name = value; } }
public Mobile()
{
Container = new MobileSerialContainer(this);
}
public Mobile(MobileSerialContainer container)
{
Container = container;
}
public void Delete()
{
Container.Delete();
}
private MobileSerialContainer Container { get; set; }
protected static string MakeSafeString(string value)
{
if (string.IsNullOrEmpty(value))
return value;
return value.Replace("&", "&")
.Replace(",", ",")
.Replace("=", "&eq;");
}
protected static string MakeUnsafeString(string value)
{
if (string.IsNullOrEmpty(value))
return value;
return value.Replace("&eq;", "=")
.Replace(",", ",")
.Replace("&", "&");
}
public virtual string Serialize()
{
string result = "";
var properties = PersistentProperties;
foreach (var property in properties)
{
string name = MakeSafeString(property.Name);
var value = property.GetValue(this, null);
string unsafeValueString = (string)Convert.ChangeType(value, typeof(string));
string valueString = MakeSafeString(unsafeValueString);
result += name + "=" + valueString + ",";
}
return result;
}
public virtual void Deserialize(string serialized)
{
var properties = PersistentProperties.ToList();
var entries = serialized.Split(',');
foreach (var entry in entries)
{
if (string.IsNullOrEmpty(entry))
continue;
var keyPair = entry.Split('=');
if (keyPair.Length != 2)
continue;
string name = MakeUnsafeString(keyPair[0]);
string value = MakeUnsafeString(keyPair[1]);
var property = properties.FirstOrDefault(p => p.Name == name);
if (property == null)
continue;
object rawValue = Convert.ChangeType(value, property.PropertyType);
property.SetValue(this, rawValue, null);
}
}
protected IEnumerable<PropertyInfo> PersistentProperties
{
get
{
var type = GetType();
var properties = type.GetProperties().Where(p => p.GetCustomAttributes(typeof(PersistAttribute), true).Any());
return properties;
}
}
}
Several layers above this, I have the System layer, in which I have the class Person:
public class Person : Mobile
{
[Persist]
public string LastName { get; set; }
}
The basic idea is this: I want the System layer to have almost no knowledge of the Data layer. It creates anything that extends "Mobile", which is automatically saved to the database. I don't want to have a table for Person, hence the weird serialization stuff, because there are literally hundreds of classes that extend Mobile. I don't want hundreds of tables. All of this serialization stuff works perfectly, the SerializedString bit, saving everything, reloading, etc etc. The only thing I haven't come up with a solution for is:
I don't want to have to implement the two constructors to Person:
public Person() : base() { }
public Person(MobileSerialContainer container)
: base(container) { }
as that requires the System layer to have more knowledge of the Data layer.
The weird serialization string thing stays. The reflection business stays. I know it's slow, but database writes and reads are very rare, and asynchronous anyway.
Besides that, I'm looking for any cool ideas about how to resolve this. Thanks!
[edit]
Changed a miswritten line of code in the MobileSerialContainer class pasted here.
If you are rewriting your application, you could reconsider all the design of your system to keep your domain layer (System layer) independent from your Data Access layer using :
A repository pattern to handle access to your database (dataContext)
A domain layer for your business objects (mobile and stuff)
Inversion Of Control pattern (IOC) to keep your layers loosely coupled
The inheritance stuff is definitively not the good way to go to keep a system loosely coupled.
What you want is type.GetConstructors() not type.GetConstructor(), this will let you get the base constructors and pass the type you are looking for.
I need a Login function(login is just an example, any other frequently used method can be fine) which takes email and password as parameter and asks DB if there is such a user. If yes, it has to return customer_id(int), if no, it will return the message why login could not happen(ex:no such an email address).
I also do not wanna rewrite the login function everytime. I want to write it once in a common project which I can use in my every project and reuse it. But i am trying to find out the best practice for this. So far, i thought something like below, but the problem for me is that i cannot return customerID which i will get in codebehind in my projects(any other project) and open a session variable with it. I only can return strings in below structure. I also thought returning a Dic, but this also is wrong I guess because if bool(key) happens to be true, customerID is not a string(value). Can you help me please learning the correct way of using common functions with no need to think the returning messages and variables twice? Thanks a lot
public class UserFunctions
{
private enum Info
{
//thought of returning codes??
LoginSuccess = 401,
NoMatchPasswordEmail = 402,
InvalidEmail = 403,
};
public string TryLogin(string email, string password)
{
bool isValidEmail = Validation.ValidEmail(email);
if (isValidEmail == false)
{
return Result(Info.InvalidEmail);
// returning a message here
}
Customers customer = new Customers();
customer.email = email;
customer.password = password;
DataTable dtCustomer = customer.SelectExisting();
if (dtCustomer.Rows.Count > 0)
{
int customerID = int.Parse(dtCustomer.Rows[0]["CustomerID"].ToString());
return Result(Info.LoginSuccess);
// Here I cant return the customerID. I dont wanna open a session here because this function has no such a job. Its other projects button events job I guess
}
else
{
return Result(Info.NoMatchPasswordEmail);
}
}
private string Result(Info input)
{
switch (input)
{
case Info.NoMatchPasswordEmail:
return "Email ve şifre bilgisi uyuşmamaktadır";
case Info.InvalidEmail:
return "Geçerli bir email adresi girmelisiniz";
case Info.LoginSuccess:
return "Başarılı Login";
}
return "";
}
}
You may want to consider returning an instance of a custom class.
public class LoginResult
{
public Info Result { get; set; }
public int CustomerId { get; set;}
}
Modify your TryLogin method to return an instance of LoginResult.
Base your application flow on the result:
var loginResult = TryLogin(..., ...);
switch (loginResult.Result)
{
case Info.LoginSuccess:
var customerId = loginResult.CustomerId;
//do your duty
break;
case Info.NoMatchPasswordEmail:
//Yell at them
break;
...
}
You could try Creating an event and then the calling code can register to the event before attempting to login.
For example:
public class UserFunctions
{
private enum Info
{
LoginSuccess = 401,
NoMatchPasswordEmail = 402,
InvalidEmail = 403,
};
public delegate void LoginAttemptArgs(object sender, Info result, int CustomerID);//Define the delegate paramters to pass to the objects registered to the event.
public event LoginAttemptArgs LoginAttempt;//The event name and what delegate to use.
public void TryLogin(string email, string password)
{
bool isValidEmail = Validation.ValidEmail(email);
if (isValidEmail == false)
{
OnLoginAttempt(Info.InvalidEmail, -1);
}
Customers customer = new Customers();
customer.email = email;
customer.password = password;
DataTable dtCustomer = customer.SelectExisting();
if (dtCustomer.Rows.Count > 0)
{
int customerID = int.Parse(dtCustomer.Rows[0]["CustomerID"].ToString());
OnLoginAttempt(Info.LoginSuccess, customerID);
}
else
{
OnLoginAttempt(Info.NoMatchPasswordEmail, -1);
}
}
private void OnLoginAttempt(Info info, int CustomerID)
{
if (LoginAttempt != null)//If something has registered to this event
LoginAttempt(this, info, CustomerID);
}
}
I wouldn't compile a string to return, I would return the enum result and let the calling code do what it likes with the result. reading an enum is much quicker than parsing returned string.
Edit: Typos and i missed an event call... .Twice