[c#] Databinding 타입을 안전하게 만들고 리팩토링을 지원하는 방법


Answers

nameof 연산자는 C # 6.0에서 .NET 4.6 및 VS2015 (2015 년 7 월)로 구현되었습니다. 다음은 C # <6.0에서도 유효합니다.

속성 이름을 포함하는 문자열을 피하기 위해 표현식 트리를 사용하여 멤버의 이름을 반환하는 간단한 클래스를 작성했습니다.

using System;
using System.Linq.Expressions;
using System.Reflection;

public static class Member
{
    private static string GetMemberName(Expression expression)
    {
        switch (expression.NodeType)
        {
            case ExpressionType.MemberAccess:
                var memberExpression = (MemberExpression) expression;
                var supername = GetMemberName(memberExpression.Expression);

                if (String.IsNullOrEmpty(supername))
                    return memberExpression.Member.Name;

                return String.Concat(supername, '.', memberExpression.Member.Name);

            case ExpressionType.Call:
                var callExpression = (MethodCallExpression) expression;
                return callExpression.Method.Name;

            case ExpressionType.Convert:
                var unaryExpression = (UnaryExpression) expression;
                return GetMemberName(unaryExpression.Operand);

            case ExpressionType.Parameter:
                return String.Empty;

            default:
                throw new ArgumentException("The expression is not a member access or method call expression");
        }
    }

    public static string Name<T>(Expression<Func<T, object>> expression)
    {
        return GetMemberName(expression.Body);
    }

    public static string Name<T>(Expression<Action<T>> expression)
    {
        return GetMemberName(expression.Body);
    }
}

이 클래스는 다음과 같이 사용할 수 있습니다. 비록 코드에서만 사용할 수 있지만 (XAML에서는 그렇지 않다), 적어도 (적어도 나를 위해) 도움이된다. 그러나 코드는 여전히 타입 안전하지 않다. 함수의 반환 값을 정의하는 두 번째 형식 인수를 사용하여 메서드 이름을 확장 할 수 있습니다.이 형식 인수는 속성 형식을 제한합니다.

var name = Member.Name<MyClass>(x => x.MyProperty); // name == "MyProperty"

지금까지는 데이터 바인딩 유형 안전 문제를 해결할만한 것을 찾지 못했습니다.

친애하는

Question

객체의 속성에 컨트롤을 바인딩하려면 속성의 이름을 문자열로 제공해야합니다. 이는 다음과 같은 이유로 그리 좋지 않습니다.

  1. 속성을 제거하거나 이름을 변경하면 컴파일러 경고 메시지가 표시되지 않습니다.
  2. 리팩토링 도구를 사용하여 속성의 이름을 바꾸면 데이터 바인딩이 업데이트되지 않을 수 있습니다.
  3. 속성의 유형이 잘못된 경우 런타임까지 오류가 발생하지 않습니다 (예 : 날짜 선택기에 정수 바인딩).

디자인 패턴이 둥글게되지만 여전히 데이터 바인딩의 사용 편의성이 있습니까?

(이것은 WinForm, Asp.net, WPF 및 다른 시스템에서 가장 많이 발생할 수있는 문제입니다)

나는 이제 솔루션에 대한 좋은 시작점을 가지고있는 " C # : typesafe databinding "의 nameof () 연산자에 대한 해결 방법을 발견했습니다.

코드를 컴파일 한 후 포스트 프로세서를 사용하고자한다면 notifypropertyweaver 가치가 있습니다.

누구나 WPF에 대한 좋은 해결책을 알고 있는데, 바인딩이 XML이 아닌 C #로 끝나면?




이 블로그 기사에서는이 접근법의 성능에 대해 좋은 질문을 제기 합니다. 일종의 정적 초기화의 일부로 표현식을 문자열로 변환하여 이러한 단점을 개선 할 수 있습니다.

실제 메커니즘은보기 흉하게 보일 수도 있지만 여전히 형식이 안전하며 원시 INotifyPropertyChanged와 거의 동일한 성능을 보입니다.

이런 종류의 :

public class DummyViewModel : ViewModelBase
{
    private class DummyViewModelPropertyInfo
    {
        internal readonly string Dummy;

        internal DummyViewModelPropertyInfo(DummyViewModel model)
        {
            Dummy = BindingHelper.Name(() => model.Dummy);
        }
    }

    private static DummyViewModelPropertyInfo _propertyInfo;
    private DummyViewModelPropertyInfo PropertyInfo
    {
        get { return _propertyInfo ?? (_propertyInfo = new DummyViewModelPropertyInfo(this)); }
    }

    private string _dummyProperty;
    public string Dummy
    {
        get
        {
            return this._dummyProperty;
        }
        set
        {
            this._dummyProperty = value;
            OnPropertyChanged(PropertyInfo.Dummy);
        }
    }
}



1. 속성이 제거되거나 이름이 변경되면 컴파일러 경고 메시지가 표시되지 않습니다.

2. 리팩토링 툴을 사용하여 속성의 이름을 변경하면 데이터 바인딩이 업데이트되지 않을 가능성이 있습니다.

3. 날짜 선택기에 정수를 바인딩하는 것과 같이 속성의 유형이 잘못된 경우 런타임까지 오류가 발생하지 않습니다.

예, 이안, 정확히 이름 문자열 기반의 데이터 바인딩 문제입니다. 당신은 디자인 패턴을 요구했습니다. Model-View-ViewModel (MVVM) 패턴의 View Model 부분의 구체화 인 Type-Safe View Model (TVM) 패턴을 디자인했습니다. 그것은 당신 자신의 대답과 비슷한 타입 안전 바인딩에 기반합니다. 방금 WPF 용 솔루션을 게시했습니다.

http://www.codeproject.com/Articles/450688/Enhanced-MVVM-Design-w-Type-Safe-View-Models-TVM




Related