2015-02-21 5 views
0

Доброго дня,Найти родительский класс от собственности

Я не совсем уверен, как фраза на мой вопрос, поэтому, пожалуйста, простите все, что не имеет отношения, и, если я оставил что-нибудь важные, пожалуйста, дай мне знать! Я также неопытен с lambdas, regex и linq, так что сделайте что-нибудь, что я делаю плохо/может быть лучше.

Мой вопрос: могу ли я получить ссылку на класс, из которого я знаю только свойство? В частности, в следующем фрагменте кода я хотел бы изменить индекс 0 в propertyValues[0] на переменную, хранящуюся в том же классе. Есть что-то вроде: this, который обращается к родительскому?

Для получения более подробной информации я вставил соответствующий снимок ниже.

return Regex.Replace (originalString, "{(.*?)}", match => 
    User.user.properties.First(property => 
     property.id == match.ToString().Substring (1, match.ToString().Length - 2)) 
      .propertyValues[0].adjectives[0]); 



public class Property 
{ 

    public string id; 
    public List<Value> propertyValues = new List<Value>(); 
    public sbyte propertyIndex; 

} 

Спасибо, что нашли время, чтобы прочитать это!

EDIT

Спасибо за обратную связь, Филипп Stuyck я постараюсь сделать лучше объяснить.

Я также ищу способ получить ссылку на родительский класс свойства или способ создания локальной переменной в выражении лямбда. Для иллюстрации у меня есть следующий класс и метод возврата.

класс недвижимости,

public class Property 
{ 

    public string id; 
    public List<Value> propertyValues = new List<Value>(); 
    public sbyte propertyIndex; 

} 

класс пользователя,

public class User 
{ 

    public static User user = new User(); 

    internal List<Property> properties = new List<Property>(); 
} 

GetVariable метод,

public static class GetVariable 
{ 

    public static string FromUser (string originalString) 
    { 

     return Regex.Replace (originalString, "{(.*?)}", match => User.user.properties.First (property => property.id == match.ToString().Substring (1, match.ToString().Length - 2)).propertyValues[0].adjectives[0]); 
    } 
} 

Метод GetVariable.FromUser должен вернуть новую строку, которая заменила каждый экземпляр подстрока, заключенная в скобки с строкой от User.user.properties , Таким образом, он может быть передан «Это {Пример}.» И вернуть «Это демонстрация» (если у класса User было свойство с примером id и значением Demo).

Мой вопрос связан с методом GetVariable, а точнее, с последней частью: propertyValues[0]. Я хотел бы, чтобы индекс (в настоящее время 0) был переменной в классе Property, который находит делегат User.user.properties.First.

В идеале это будет так же просто, как User.user.properties.First (property => property.id == match.ToString()).propertyValues[property.propertyIndex], но я не могу получить доступ к свойству вне круглых скобок.

Надеюсь, это помогло объяснить это, хотя я чувствую, что все еще слишком сложно. Если я смогу придумать лучший способ рассказать о моем вопросе, я сделаю это. Кроме того, я буду рад прояснить что-либо посредством комментария.

+0

Полностью не понимаю, что вы имеете в виду. Пожалуйста, перефразируйте полностью. –

+0

@PhilipStuyck Спасибо за комментарий! Я попытался перефразировать мой вопрос, надеюсь, теперь это станет более ясным. Я не очень хорошо объясняю эти вопросы, поэтому, пожалуйста, простите мою бедную работу раньше. Если он все еще слишком расплывчатый, пожалуйста, спросите в комментариях, поэтому я могу попытаться сделать его более понятным. Еще раз спасибо! –

ответ

1

Короче говоря, нет. Если у вас есть ссылка на объект, вы можете получить от него потенциально неизвестное свойство, используя Reflection, но вы не можете найти произвольный объект, если у вас есть свойство. Это имеет смысл, потому что, если у вас есть какое-то свойство, называемое Id, это может быть свойство для любого объекта, так как C# даже попытается начать разрешать это обратно к типу - не говоря уже о конкретном экземпляре этого типа.

Если вы знаете, что экземпляр у вас есть, вы можете можете использовать отражение, как так:

var myProperty = myInstance.GetType().GetProperty("Id"); 
myProperty.SetMethod.Invoke(myInstance, new object[] {42}); 
//this will set the given property on the given 
//instance with the given value (42 in this example) 
//GetMethod is also there 
//depending on what you need to do with it 

Однако следует уточнить, что выше отражение работает только с Свойства, и в вашем примере у вас есть поля, поэтому вам нужно будет получить FieldInfo, который немного отличается от свойств.

Но в приведенном выше примере это кажется неясным, похоже, у вас есть как экземпляр и знать тип, так почему вы не можете просто использовать:

Regex.Replace ( 
    originalString, 
    "{(.*?)}", 
    match => 
     User.user.properties.First(property => 
     property.id == match.ToString().Substring(1, 
           match.ToString().Length - 2)) 
       .propertyValues[(int)property.propertyIndex] 
       .adjectives[0]); 

Если я не я не ясно, на что вы спрашиваете, похоже, что это сработает?

UPDATE

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

Что-то вроде этого, я думаю, что это то, что вы ищете:

return Regex.Replace ( 
    originalString, 
    "{(.*?)}", 
    match => 
    { 
     var matchStr = match.ToString() 
     var formattedMatch = matchStr.Substring(1, matchStr.Length - 2); 
     var prop = User.user.properties.First(
       property => property.id == formattedMatch); 
     return prop.propertyValues[(int)prop.propertyIndex].adjectives[0]; 
    } 

TL; DR

я, вероятно, следует упомянуть, как вы сказали, что вы новичок в Linq и лямбды, по существу Expression<T> или LambdaExpression - это Func<TArgs..>, который скомпилирован во время выполнения, а не во время компиляции, поэтому то, что вы делаете, когда вы пишете c => c.Id == 42, создает метод, который выглядит так:

internal static int _closureVariable = 42; 
public static bool checkName(Property prop) 
{ 
    return prop.Id == _closureVariable; 
} 

Есть немного больше связанных с тем, как он обрабатывается и генерируется, но конечный результат схож.

Так в моем примере с телом метода, я просто создать более сложный метод, который имеет подпись, как это:

public static string matchRegex(Match match); 

, а затем вся работа происходит внутри этого метода подписи. Важно помнить, что, когда тело не объявлено в выражении, ключевое слово return неявно (т.е. c => c.Name == "some name" неявно возвращает true), поэтому, если у вас есть тело метода (c => { ... }), вам нужно явно объявить возврат или он вернется недействительным. (то есть c => { return c.Name == "some name"}).

+0

Топхаллен, спасибо за ответ. Я хотел бы сделать что-то похожее на ваш последний пример, но ссылка 'property' не существует вне свойств. Первый делегат. Я тоже надеялся избежать размышлений, но это может быть то, что я должен сделать. Есть ли способ назначить ссылку в выражении лямбда? –

+1

см. Мой обновленный ответ, должно быть то, что вы ищете – tophallen

+0

Я понятия не имел, что можно было создать метод из делегата, спасибо большое! –

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