2015-12-04 4 views
0

Я знаю, что этот вопрос звучит так, будто это может быть дубликат, но я не мог найти ничего, связанного с тем, что я собираюсь описать.Передача общего объекта методу в C#

Я пытаюсь создать проект шаблонов электронной почты html. У меня есть ViewModel (только называя их, что для ясности, что они просто классы со свойствами, необходимыми для этой электронной почты для передачи значений, которые должны быть заменены в шаблоне)

public class EmailViewModels 
{ 
    public class AccountClosedEmailViewModel 
    { 
     public string Fullname { get; set; } 
     public string ApplicationName { get; set; } 
     public string Username { get; set; } 
     public string RenewRegistrationUrl { get; set; } 
    } 

    public class AccountReopenedEmailViewModel 
    { 
     public string Fullname { get; set; } 
     public string ApplicationName { get; set; } 
     public string Username { get; set; } 
     public string RenewRegistrationUrl { get; set; } 
     public string CancelVerificationUrl { get; set; } 
    } 

    public class ContactFormEmailViewModel 
    { 
     public string Fullname { get; set; } 
     public string ApplicationName { get; set; } 
    } 
    //rest removed for brevity 
} 

хочет метод, который принимает по электронной почте view model, это может быть любой из тех, которые определены в вышеприведенном классе, поэтому у меня есть общий метод, чтобы исключить меня с помощью BuildHtmlFromTemplate для каждого типа модели представления.

public string BuildHtmlFromTemplate(templateFilePath, passing any one of the email viewmodels defined in the class) 
{ 
    var temp = File.IO.ReadAllText(templateFilePath); 
    temp.Replace("{username}", modelipassedin.username); 
    //do rest 
    return temp; 

} 

Возможно ли это?

+0

что вы хотите сделать внутри _BuildHtmlFromTemplate_? почему бы не добавить функцию для каждого класса? – Grundy

+0

Ну, у вас может быть параметр типа 'object' ... но мы не знаем, что этот метод должен делать - как выглядит код. Например, вы можете использовать отражение, чтобы найти свойства. –

+0

@JonSkeet и использовать общий объект вместо объекта BuildHtmlFromTemplate (T o) ' – Grundy

ответ

3

Вы можете использовать отражение и дженерики, как этот

public string BuildHtmlFromTemplate<T>(templateFilePath, T o) 
{ 
    var temp = File.IO.ReadAllText(templateFilePath); 
    foreach(var prop in typeof(T).GetProperties()){ 
     temp = temp.Replace("{"+prop.Name+"}", prop.GetValue(o)); 
    } 
    return temp; 
} 

Или без дженериков

public string BuildHtmlFromTemplate(templateFilePath, object o) 
{ 
    var temp = File.IO.ReadAllText(templateFilePath); 
    foreach(var prop in o.GetType().GetProperties()){ 
     temp = temp.Replace("{"+prop.Name+"}", prop.GetValue(o)); 
    } 
    return temp; 
} 
+0

Дженерики не приносят ничего полезного в этом случае. –

+0

@KubaWyrostek, yep, вместо этого может использовать _object_ и _o.GetType() _ вместо _typeof (T) _ – Grundy

+1

Общий подход с 'typeof (T)' может завершиться неудачно, если вы не знаете точный тип при компиляции (т.е. if передавая базовый класс или «объект»). – Groo

2

Если вы хотите, чтобы иметь возможность получить доступ к свойствам объекта по имени, независимо от их типа, то вы можете:

  1. Использование отражения или

  2. Включите все классы в словарях.

Чтобы получить значение свойства по его имени с помощью отражения, вы бы использовать что-то вроде:

public static object GetValue(this object @this, string property) 
{ 
    return @this.GetType().GetProperty(property).GetValue(@this, null); 
} 

Вы могли бы использовать регулярное выражение для поиска и сразу заменить заполнители:

var inputHtml = @"<h1>{title}</h1> <p>{text}</p>"; 
var instance = new 
{ 
    title = "some title", 
    text = "some text" 
}; 

// note: not much error checking here, and 
// placeholder casing is important 

var regex = new Regex("{(.*?)}"); 
var outputHtml = regex.Replace(inputHtml, m => 
{ 
    var placeholder = m.Groups[1].Value; 

    var prop = instance.GetType().GetProperty(placeholder); 
    if (prop == null) 
     return ""; 

    return prop.GetValue(instance).ToString(); 
}); 

Для второго подхода вы просто храните свои данные как KeyValuePair<string, string> и выполните простую замену строк.

+0

интересная мысль о словарях. Я полагаю, что у меня мог бы быть заполнитель в качестве ключа и связанного с ним свойства модели как его значение и просто петля через пары – dinotom

+0

@dinotom: да, это самое слабо типизированное решение и позволяет избежать необходимости в отражении. Но это также упрощает ввод данных (т. Е. Вы можете просто иметь таблицу с столбцами «имя» и «значение», чтобы ввести кучу значений). – Groo

+0

Я думал больше о том, что метод в классе возвращает словарь, где имя свойства как строка является ключом, а значение свойства - значением и передает этот словарь в метод BuildHtmlMethod. я должен был бы настроить мои шаблоны, чтобы заполнители точно соответствовали именам свойств класса. Будет ли это работать? – dinotom

-2
public class EmailViewModel 
{ 
    public string ToHTMLString() 
    { 
    //And use reflection on the properties here. 
    } 
} 

public class AccountClosedEmailViewModel:EmailViewModel { 
    public string Fullname { get; set; } 
    public string ApplicationName { get; set; } 
    public string Username { get; set; } 
    public string RenewRegistrationUrl { get; set; } 
} 

public class AccountReopenedEmailViewModel:EmailViewModel{ 
    public string Fullname { get; set; } 
    public string ApplicationName { get; set; } 
    public string Username { get; set; } 
    public string RenewRegistrationUrl { get; set; } 
    public string CancelVerificationUrl { get; set; } 
} 

public class ContactFormEmailViewModel:EmailViewModel { 
    public string Fullname { get; set; } 
    public string ApplicationName { get; set; } 
} 

Edit: И таким образом, вы можете переместить некоторые из общих свойств в базовом классе для того, чтобы каждая модель немного легче.

Смежные вопросы