在Mike Taulty的视频教程中有一个动态加载silverlight应用程序的DEMO,其程序运行效果如下:
当加载dll之后:
其实实现这个的效果本身并不难,主要是这个DEMO的应用场景可以让人做很大的扩展,比如说插
件机制等.
好了,让我们看看如何实际去开发这个示例,以便让大家从流程和技术点上有个了解.
首先我们需要建立一个叫DynamicLoading的silverlight Application, 然后将如下的内容拷贝
到Page.xaml中:
<
UserControl
x:Class
="DynamicLoading.Page"
xmlns
="http://schemas.microsoft.com/client/2007"
xmlns:x
="http://schemas.microsoft.com/winfx/2006/xaml"
Width
="400"
Height
="300"
>
<
Grid
x:Name
="LayoutRoot"
Background
="White"
>
<
Grid.RowDefinitions
>
<
RowDefinition
/>
<
RowDefinition
/>
</
Grid.RowDefinitions
>
<
StackPanel
>
<
StackPanel
>
<
TextBox
Width
="200"
x:Name
="txtPlugIn"
Margin
="10"
Text
="Implementation.dll"
/>
</
StackPanel
>
<
Button
HorizontalAlignment
="Center"
Margin
="10"
Width
="96"
Content
="加载DLL"
Click
="OnClick"
/>
</
StackPanel
>
<
Grid
Grid.Row
="1"
Background
="AliceBlue"
Margin
="20"
x:Name
="gridHosting"
>
</
Grid
>
<
StackPanel
VerticalAlignment
="Bottom"
>
<
TextBlock
x:Name
="txtToEdit"
FontSize
="16"
FontStyle
="italic"
Text
="编辑内容"
TextAlignment
="center"
HorizontalAlignment
="Stretch"
Grid.Row
="2"
VerticalAlignment
="Center"
/>
</
StackPanel
>
</
Grid
>
</
UserControl
>
然后我们需要先建立一个接口文件(类似于插件接口),所以在当前SLN下新加一个Silverlight Class
Library 项目,名称为:Interfaces .将class.cs文件改名为:IEditText.cs .
将如下接口内容拷贝到该cs文件中:
public
class
TextChangedEventArgs : EventArgs
{
public
string
Text {
get
;
set
; }
}
public
interface
IEditText
{
UIElement GetControls();
void
SetText(
string
text);
event
EventHandler
<
TextChangedEventArgs
>
TextChanged;
}
编译这个接口项目.接下来我们将会实现这个接口(相当于实际的插件功能).
我们再新建一个叫Implementation的Silverlight Class Library 项目,重命名class.cs文件为Editor.cs
, 将如下内容拷贝到项目的cs文件中:
public
class
Editor : Interfaces.IEditText
{
TextBox textBox;
public
Editor()
{
textBox
=
new
TextBox();
}
//
插件运行时加载的控件(界面)
public
UIElement GetControls()
{
StackPanel Panel
=
new
StackPanel();
StackPanel stackPanel
=
new
StackPanel();
stackPanel.Margin
=
new
Thickness(
5
);
stackPanel.Orientation
=
Orientation.Horizontal;
textBox
=
new
TextBox();
textBox.Width
=
300
;
textBox.Height
=
70
;
Button button
=
new
Button();
button.Content
=
"
点击这里
"
;
button.Click
+=
OnButtonClick;
button.Width
=
60
;
stackPanel.Children.Add(textBox);
Panel.Children.Add(stackPanel);
Panel.Children.Add(button);
return
Panel;
}
public
void
SetText(
string
text)
{
textBox.Text
=
text;
}
//
将点击提交按钮时,更新相应的界面内容
void
OnButtonClick(
object
sender, EventArgs args)
{
if
(TextChanged
!=
null
)
{
TextChanged(
this
,
new
Interfaces.TextChangedEventArgs()
{
Text
=
textBox.Text
});
}
}
public
event
EventHandler
<
Interfaces.TextChangedEventArgs
>
TextChanged;
}
之后,我们编译一下译项目.
下面看一下加载上面类库的代码(位于Page.xaml.cs文件中):
public
partial
class
Page : UserControl
{
public
Page()
{
InitializeComponent();
}
//
点击加载按钮事件
void
OnClick(
object
sender, EventArgs args)
{
//
获取要加载的dll文件信息
string
assembly
=
txtPlugIn.Text;
WebClient client
=
new
WebClient();
//
准备获取dll文件的信息
client.OpenReadCompleted
+=
OnReadCompleted;
client.OpenReadAsync(
new
Uri(assembly, UriKind.Relative));
}
void
OnReadCompleted(
object
sender, OpenReadCompletedEventArgs e)
{
AssemblyPart part
=
new
AssemblyPart();
//
获取加载的dll信息(stream格式)
Assembly assembly
=
part.Load(e.Result);
//
构造该对象(插件)的实例
IEditText editor
=
assembly.CreateInstance(
"
Implementation.Editor
"
)
as
IEditText;
if
(editor
!=
null
)
{
//
加载其中的控件(gridHosting类型为<Grid>)
gridHosting.Children.Add(editor.GetControls());
editor.SetText(txtToEdit.Text);
//
完成事件绑定
editor.TextChanged
+=
OnTextChanged;
}
}
//
内容更新
void
OnTextChanged(
object
sender, Interfaces.TextChangedEventArgs e)
{
txtToEdit.Text
=
e.Text;
}
}
当然要编译还要引用一下前面写的接口项目(Interfaces),这样代码部分就完成了.这里我们还
要将类库Implementation.dll(插件)放入web项目中的ClientBin文件夹下.这样我们就可以运行文章
开始处的页面了.
是不是很简单,这里面主要的一块内容就是使用WebClient读取dll文件,如下:
WebClient client
=
new
WebClient();
client.OpenReadCompleted
+=
OnReadCompleted;
client.OpenReadAsync(
new
Uri(assembly, UriKind.Relative));