TypeDescriptionProvider
Juan Carlos Diaz가 작동하지 않고 조건부 컴파일도 마음에 들지 않는다고 말하는 사람들을위한 몇 가지 팁 이 있습니다.
우선, 코드 변경 사항이 폼 디자이너에서 작동하도록 Visual Studio 를 다시 시작 해야 할 수 있습니다 (매번 간단한 다시 빌드가 작동하지 않았거나 그렇지 않음).
추상 기반 양식의 경우이 문제에 대한 해결책을 제시하겠습니다. BaseForm
클래스가 있고이를 기반으로하는 모든 양식을 디자인 할 수 있기를 원한다고 가정 해 보겠습니다 ( Form1
). 는 TypeDescriptionProvider
후안 카를로스 디아즈에 의해 제시된 또한 나를 위해 작동하지 않았다. 다음은 MiddleClass 솔루션과 결합하여 (smelch로) 조건부 컴파일 및 일부 수정 없이#if DEBUG
작동하도록 만든 방법입니다 .
[TypeDescriptionProvider(typeof(AbstractControlDescriptionProvider<BaseForm, BaseFormMiddle2>))] // BaseFormMiddle2 explained below
public abstract class BaseForm : Form
{
public BaseForm()
{
InitializeComponent();
}
public abstract void SomeAbstractMethod();
}
public class Form1 : BaseForm // Form1 is the form to be designed. As you see it's clean and you do NOTHING special here (only the the normal abstract method(s) implementation!). The developer of such form(s) doesn't have to know anything about the abstract base form problem. He just writes his form as usual.
{
public Form1()
{
InitializeComponent();
}
public override void SomeAbstractMethod()
{
// implementation of BaseForm's abstract method
}
}
BaseForm 클래스의 속성을 확인하십시오. 그럼 당신은 단지 선언해야 TypeDescriptionProvider
하고 이 중산층을 그들이,하지만 걱정하지 Form1의 개발에 대한 보이지 않는 무관 . 첫 번째는 추상 멤버를 구현하고 기본 클래스를 추상이 아닌 것으로 만듭니다. 두 번째는 비어 있습니다. VS 양식 디자이너가 작동하는 데 필요합니다. 그럼 당신은 지정 둘째 받는 중산층 TypeDescriptionProvider
의 BaseForm
. 조건부 컴파일이 없습니다.
두 가지 문제가 더 있습니다.
- 문제 1 : 디자이너 (또는 일부 코드)에서 Form1을 변경 한 후 다시 오류가 발생했습니다 (디자이너에서 다시 열려고 할 때).
- 문제 2 : 디자이너에서 Form1의 크기가 변경되고 폼이 닫혔다가 폼 디자이너에서 다시 열릴 때 BaseForm의 컨트롤이 잘못 배치되었습니다.
첫 번째 문제 (내 프로젝트에서 다른 곳에서 저를 괴롭 히고 일반적으로 "유형 X를 유형 X로 변환 할 수 없음"예외를 생성하기 때문에 문제가 없을 수 있습니다). 유형 을 비교하는 대신 유형 이름 (FullName) TypeDescriptionProvider
을 비교하여 해결했습니다 (아래 참조).
두 번째 문제입니다. 기본 폼의 컨트롤이 Form1 클래스에서 디자인 할 수없고 크기 조정 후 위치가 손실되는 이유는 모르겠지만 해결했습니다 (좋은 해결책이 아닙니다. 더 잘 알고 있다면 작성하십시오). BaseForm의 Load 이벤트에서 비동기 적으로 호출 된 메서드에서 BaseForm의 버튼 (오른쪽 하단 모서리에 있어야 함)을 올바른 위치로 수동으로 이동합니다. BeginInvoke(new Action(CorrectLayout));
기본 클래스에는 "OK"및 "Cancel"버튼 만 있습니다. 케이스는 간단합니다.
class BaseFormMiddle1 : BaseForm
{
protected BaseFormMiddle1()
{
}
public override void SomeAbstractMethod()
{
throw new NotImplementedException(); // this method will never be called in design mode anyway
}
}
class BaseFormMiddle2 : BaseFormMiddle1 // empty class, just to make the VS designer working
{
}
그리고 여기에 약간 수정 된 버전이 있습니다 TypeDescriptionProvider
.
public class AbstractControlDescriptionProvider<TAbstract, TBase> : TypeDescriptionProvider
{
public AbstractControlDescriptionProvider()
: base(TypeDescriptor.GetProvider(typeof(TAbstract)))
{
}
public override Type GetReflectionType(Type objectType, object instance)
{
if (objectType.FullName == typeof(TAbstract).FullName) // corrected condition here (original condition was incorrectly giving false in my case sometimes)
return typeof(TBase);
return base.GetReflectionType(objectType, instance);
}
public override object CreateInstance(IServiceProvider provider, Type objectType, Type[] argTypes, object[] args)
{
if (objectType.FullName == typeof(TAbstract).FullName) // corrected condition here (original condition was incorrectly giving false in my case sometimes)
objectType = typeof(TBase);
return base.CreateInstance(provider, objectType, argTypes, args);
}
}
그리고 그게 다야!
BaseForm을 기반으로하는 향후 양식 개발자에게 아무것도 설명 할 필요가 없으며 양식을 디자인하기 위해 어떤 트릭도 할 필요가 없습니다! 나는 그것이 가능한 가장 깨끗한 솔루션이라고 생각합니다 (컨트롤 재배치 제외).
추가 팁 :
어떤 이유로 디자이너가 여전히 작업을 거부하는 경우 코드 파일에서 public class Form1 : BaseForm
to public class Form1 : BaseFormMiddle1
(또는 BaseFormMiddle2
)를 변경하고 VS 양식 디자이너에서 편집 한 다음 다시 변경 하는 간단한 트릭을 수행 할 수 있습니다 . 조건부 컴파일보다이 트릭을 선호합니다. 왜냐하면 잘못된 버전을 잊고 릴리스 할 가능성이 적기 때문 입니다.