目录
一、概述
在我们工作中,为了开发效率,避免不了需要使用一些框架,大部分框架初始化时,必须要向框架入口传入一些参数,以实现不同的功能,那么问题来了,框架入口的写法是如何实现的呢?
我们就以 NanUI 这个框架作为例子,看看这个框架的启动入口,看起来就非常的优雅好看吧,其实实现这个效果也不难,而且没有那么多高级语法,那么这次就以 NanUI 框架这个启动入口来写一个类似的 Demo 出来,学习这些知识之前,你必须了解 C# 的委托,Lambda 表达式的一些基础知识,后面我也会做一些相关的介绍。
NanUI 的框架入口:
using NetDimension.NanUI;
using NetDimension.NanUI.EmbeddedFileResource;
using NetDimension.NanUI.LocalFileResource;
using NetDimension.NanUI.ZippedResource;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
using Xilium.CefGlue;
namespace NanUIFramework
{
static class Program
{
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
WinFormium.CreateRuntimeBuilder(env =>
{
env.CustomCefSettings(settings =>
{
// 在此处设置 CEF 的相关参数
});
env.CustomCefCommandLineArguments(commandLine =>
{
// 在此处指定 CEF 命令行参数
commandLine.AppendSwitch("disable-pinch");
});
}, app =>
{
//如果您希望只运行一个实例,请使用此设置
app.UseSingleInstance(() =>
{
MessageBox.Show("实例已经运行,只能运行一个实例", "Single Instance", MessageBoxButtons.OK, MessageBoxIcon.Warning);
});
//清除所有缓存文件,如cookie,历史,本地存储等。
app.ClearCacheFile();
//嵌入式资源
app.UseEmbeddedFileResource("http", "Load.Resource.Html", "View");
//读取本地资源 注册LocalFileResource处理程序,它可以处理本地文件夹中的文件资源。
//app.UseLocalFileResource("http", "Load.Local.Html", System.IO.Path.Combine(Application.StartupPath, "View"));
//读取ZIP资源
//app.UseZippedResource("http", "archive.app.local", Application.StartupPath + "\\View\\index.zip");
//实例化界面
MainIndex MainIndexs = new MainIndex();
// 指定启动窗体
app.UseMainWindow(context => MainIndexs);
})
.Build()
.Run();
}
}
}
二、Lambad 和 委托
"Lambda表达式"是一个匿名函数,是一种高效的类似于函数式编程的表达式,Lambda简化了开发中需要编写的代码量。它可以包含表达式和语句,并且可用于创建委托或表达式目录树类型,支持带有可绑定到委托或表达式树的输入参数的内联表达式。
比如有这样一个场景,在给出的List集合中找出数字大于等于18的数字,假如我们不知道有 Linq 这种东西!
详细的介绍可以参考我的帖子:
下面看看这段代码:
using System;
namespace 委托的用法
{
internal class Program
{
static void Main(string[] args)
{
Test((user) =>
{
user.Age = 23;
user.Height = 167;
user.Name = "老王";
});
Console.ReadKey();
}
static void Test(Action<UserInfo> action)
{
UserInfo userInfo = new UserInfo();
action?.Invoke(userInfo);
}
}
public class UserInfo
{
public string Name { get; set; }
public int Age { get; set; }
public int Height { get; set; }
}
}
执行 Test 方法时,这么写是什么意思,换一种写法,那么它就是这样:
using System;
namespace 委托的用法
{
internal class Program
{
static void Main(string[] args)
{
Action<UserInfo> action = (UserInfo user) =>
{
user.Age = 23;
user.Height = 167;
user.Name = "老王";
};
Test(action);
Console.ReadKey();
}
static void Test(Action<UserInfo> action)
{
UserInfo userInfo = new UserInfo();
action?.Invoke(userInfo);
}
}
public class UserInfo
{
public string Name { get; set; }
public int Age { get; set; }
public int Height { get; set; }
}
}
这样是否明白多了,更简单一些它就是这样
using System;
namespace 委托的用法
{
internal class Program
{
static void Main(string[] args)
{
Test(GetUser);
Console.ReadKey();
}
static void GetUser(UserInfo user)
{
user.Age = 23;
user.Height = 167;
user.Name = "老王";
}
static void Test(Action<UserInfo> action)
{
UserInfo userInfo = new UserInfo();
action?.Invoke(userInfo);
}
}
public class UserInfo
{
public string Name { get; set; }
public int Age { get; set; }
public int Height { get; set; }
}
}
Invoke 的用法在微软官方的有介绍,调用 Invoke 后,相当于 把 userInfo 这个实例化的对象,作为参数传到了 GetUser 方法中,由 GetUser 方法进行了赋值,然后 userInfo 就有了实际的值。
UserInfo userInfo = new UserInfo();
action?.Invoke(userInfo);
如下图
三、Optional 关键字
C# 常用的关键字微软文档:
在这里我看了一下,根本找不到 Optional 这个关键字,在微软的文档中搜索,也只是找到 VB 的资料
在 VB 文档中,就是可选参数的意思,其实用法挺简单
在 C# 中,我们调用方法,必须给方法的每一个参数传值,如下
using System;
namespace 可选参数
{
internal class Program
{
static void Main(string[] args)
{
int result = Add(1, 3, 4);
Console.WriteLine("结果:{0}",result);
Console.ReadKey();
}
static int Add(int num1, int num2, int num3)
{
return num1 + num2 + num3;
}
}
}
Optional 关键字的作用:
using System;
using System.Runtime.InteropServices;
namespace 可选参数
{
internal class Program
{
static void Main(string[] args)
{
int result = Add(1, 3);
Console.WriteLine("结果:{0}",result);
Console.ReadKey();
}
static int Add([Optional] int num1, int num2, [Optional] int num3)
{
return num1 + num2 + num3;
}
}
}
运行:
[Optional] 关键字放参数所放的位置不明确,会报错
四、实现效果
根据上面的理论,我们新建一个 C# 控制台项目,代码如下
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Runtime.InteropServices;
namespace Test4
{
internal class Program
{
static void Main(string[] args)
{
Framework.Set(config =>
{
config.SetAge(5);
config.SetName("张三");
config.SetOther(mode =>
{
mode.Address = "广东省,深圳市";
mode.Height = 180;
mode.Color = "Black";
});
}, setting =>
{
setting.SetIP("127.0.0.1");
setting.SetDownloadURL("www.sfdf.com");
}).Start();
Console.ReadKey();
}
}
//框架
public class Framework
{
internal static Configuration Configurations { get; set; } = new Configuration();
internal static Setting Settings { get; set; } = new Setting();
public static Project Set([Optional] Action<Configuration> config, [Optional] Action<Setting> setting)
{
config.Invoke(Configurations);
setting.Invoke(Settings);
return new Project();
}
}
//项目
public class Project
{
public void Start()
{
Console.WriteLine("启动项目");
}
}
//配置
public class Configuration
{
public void SetAge(int age)
{
Console.WriteLine("设置年龄:" + age);
}
public void SetName(string name)
{
Console.WriteLine("设置名字:" + name);
}
public void SetOther(Action<Mode> mode)
{
Mode data = new Mode();
mode.Invoke(data);
Console.WriteLine("设置其他");
Console.WriteLine("Height:" + data.Height);
Console.WriteLine("Color:" + data.Color);
Console.WriteLine("Address:" + data.Address);
}
}
//设置
public class Setting
{
public void SetIP(string ip)
{
Console.WriteLine("设置IP:" + ip);
}
public void SetDownloadURL(string ip)
{
Console.WriteLine("下载地址:" + ip);
}
}
public class Mode
{
public int Height { get; set; }
public string Color { get; set; }
public string Address { get; set; }
}
}
运行:
结束
如果这个帖子对你有所帮助,欢迎 关注 + 点赞 + 留言
end