---
title: Expression in CSharp # 標題
description: Expression in CSharp # 描述
image: # 封面
tags: # 內部標籤
robots: index, nofollow # [no]index, [no]follow
lang: zh # language
dir: ltr # left to right or right to left
breaks: # newline style
GA: UA-168653916-1 # google analysis
disqus: hackmd
slideOptions:
transition: fade # https://revealjs.com/transitions/
theme: back
---
# Expression in C#
## 前言
最近我的 youtube 推薦影片中出現了一堆關於 C# 的 Expression 教學影片
小弟我對於 Expression 也算是小有研究
所以想說也來寫一些關於 Expression 的文章
但教學在網路上已經很多 不太想在寫重複的東西
所以 這篇我會分享關於 Expression 與我之間的一些事情
## 什麼是 Expression
這裡簡單介紹```Expression``` 對於已經了解的可以跳過這段
```Expression``` 在 C# 是指方法的[抽象語法樹(AST)](AST)
這是一個足以完整描述我們所寫下的方法的一個具有[不變性](Immutable)樹狀結構
而 ```Expression``` 與 ```Method``` 的關係
就如同 ```Type``` 與 ```Object``` 的關係
並且就像是我們可以在運行時透過 ```Type``` 來建立 ```Object```
我們也可以在運行時 透過 ```Expression``` 來建立 ```Method```
不過建立 ```Method``` 其實並不是一個 Best Practice
所以 通常比較好的應用 大多都不是建立 ```Method```
而是如同我們使用 ```Type``` 上的資訊來達到我們的目的
後面也會介紹幾個用 ```Expression```
而不是建立 ```Method``` 來達到目的的案例
## Expression And Me
### 在認識 Expression 之前
早期如果要做一些泛用的東西 通常都會使用 Reflection(反射)
也就是直接透過 Type 來調用指定的 Method 或 Property
或是使用 Activator.CreateInstance 來建立物件
但眾所皆知的這幾個作法具有很嚴重的效能問題
如果想要解決這種效能問題 就得一下跳到[MSIL](MSIL)
這是一個對於即使接觸C#一陣子的人都是極為痛苦的一件事情
直到我發現 Expression 的存在改變了這一切
---
### Object Member Accessor
我想這應該是很多擅長 Expression 的人的起點
就是可以任意存取物件的成員或是執行方法
這個東西的作法只用了足夠簡單的語法就實現了高效率的存取行為
而且可以讓我開始了解 Expression 可以做到更多的事情
我可以不用去理解與撰寫 [MSIL](MSIL)
而且以更貼近我們語法的指令來自由建構動態的方法
這導致有好一陣子我也成為了 Expression 粉
什麼事情都覺得 Expression 可以解決
~~每個人都會有年少輕狂的時候~~
甚至至今 Object Member Accessor 仍留在我常用的程式庫中
直到最終系統根本用不到這玩意 才會將他移除
[Object Member Accessor 程式碼傳送門](https://gist.github.com/dcvsling/5a052615e068e5a8651400350066b911)
#### 泛用不代表就得用這種方式來存取
其實越寫到後面越發現 我們有很多的方法來繞過這樣的硬式存取
因為每一個動態做法都會造成系統的不可預測(或不易測試)
而從閱讀其他的程式庫以及設計模式 等等的技術內容發覺
我們可以透過"設計"我們的系統來迴避掉這種硬式存取
一個很典型的案例就是
我們可以透過抽象層的專案與實作層的專案及介面
讓我們迴避掉透過動態加載的組件中
建立我們需要的物件甚至運行其方法
案例可以參考[黑暗執行續大大近期的文章](https://blog.darkthread.net/blog/aspnet-auto-dll-type-discovery/?fbclid=IwAR0HCktnt4-dfM_x5i0lyFvBdD6cVVLrV_CGBwbhxPy7dTfqcSyt9eMfP9U)前半段存取 assembly 的用法
---
### Entity Framework Query (以下簡稱 EF)
在我對於 Expression 有些許了解之後
我開始注意到
原來 EF 的查詢語法參數原來是 Expression
進而打開了我對於 EF 是如何轉為 SQL 語法
前一陣子我甚至寫了一個簡單的功能
讓 EF 的查詢可以用一個Json結構反序列化後進行轉換變成一個查詢
這樣做的目的是為了提供複雜查詢時的解決方案的一部分
[儲存庫傳送門](https://github.com/dcvsling/ExpressionForEF)
不過該專案當初是為了向某人證實
我們並不需要真的將Expression變成 Method 來實現我們的需求
以及裡面運用的技術不只有 Expression 再加上我沒寫註解
所以看不懂也不用太在意
如果對這個東西有興趣想討論的歡迎私下找我討論
#### Expression 真正的應用方式並不是轉為 Method
在看過 EF 的用法之後簡直就是開了一扇全新的大門
因為這表示可以透過LINQ的語法來轉譯成別種行為 甚至別種語言
而 System.Linq.Expressions 也提供了非常完整的功能
讓你可以更輕易地去解析轉換這些行為
而同類型的套件還有像是 Moq
---
### 受限於語言而無法或難以實現的困境
C# 其實已經可以做非常多的事情
每一種語言勢必都會受限於他自己的一些特性
而有時候可能會受限於這樣的限制
導致我們期望的做法難以或無法實現
而這件事情是我最常以 Expression 來解決困境
~~說最常也就那麼一次 畢竟碰上的機率很低~~
什麼是語言限制
例如之前提過 TypeScript 可以對於泛型如果帶入陣列型別
可以對於陣列每一個型別做明確對應這件事情
在 C# 至少到目前為止是完全不可能
所以導致 C# 在做像是 Action 和 Func 這樣的委派時
採用 code generate 的方式盡可能羅列一定範圍的實作
Expression 也可以做到這樣的事情
不過 Expression 的結果其實跟羅列那些可能性是一樣的
而且 Expression 的結果是在 runtime 不是在開發過程
所以 SDK 才會採用 羅列的方式來進行
致於我那次是如何使用的 我就不再這裡提及
而且那是為了因應開發時的需求的臨時作法
並且我也告訴對方那玩意允許的情況下最後還是拿掉比較好
也告訴他們要怎麼從當下的程式碼轉成大家常見的模式
~~當然我當初也有為了讓他易於轉換而特別設計過~~
#### Simple vs Easy
雖然我不知道每個人在面對這樣的困境時是如何做的
Expression 某種程度上是一個非常直接的 Solution
一個具有難度的困境 其解決方案勢必是複雜的
當然我們可以把 code 寫得很 easy
但是勢必會在其他地方消耗更多的時間與精力
或是隱藏了更多的理論知識在這段程式碼的背後
所以 我相信每個寫這種code的人都勢必有她的難處
而我們能做的只有在把程式碼交出去之前將他[close](OCP)
以減少後續的人的麻煩
因為或許在當下這是難解的
隨著時間進展 我們可能會想到更好的做法
或是我們可能可以不再需要這樣做
所以在困難的事情上所做的複雜解決方案
我個人覺得 除了要能用之外
還要 simple install, simple use ,simple remove
藉此彌補其複雜度 以及 實現 [OCP](OCP)
## 結語
如果你是一個常用 Type 或是常常使用 GetType 的人
Expression 是真心推薦可以好好研究一番
這兩個東西是一樣的
至於如果你遇到必須接收到一份包含 Expression 的code
而你卻完全看不懂其中在做什麼的人
與其花時間抗議看不懂
不如趁機好好問對方它是怎麼運作的
我認為寫下這樣的程式碼的人本來就應該要為此負責
而我也是如此在付諸實行
如果那個人跑了 終究還是得要自己面對他
抱怨不會讓那些語法在做什麼
但貼到網路上或是開始學習
絕對可以讓你站上更好的位置
因為抱怨在老闆和主管面前沒有解決問題
而學習並且維護別人避之唯恐不及的東西才是老闆與主管想要的人
~~如果大家都用最基本的東西在寫~~
~~沒有設計 沒有規劃 正在抱怨的你能想像~~
~~一堆強者正在搶你的飯碗 你搶的贏嗎? XD~~
# 連結
[AST](https://zh.wikipedia.org/wiki/%E6%8A%BD%E8%B1%A1%E8%AA%9E%E6%B3%95%E6%A8%B9)
[Immutable](https://zh.wikipedia.org/wiki/%E4%B8%8D%E5%8F%AF%E8%AE%8A%E7%89%A9%E4%BB%B6)
[MSIL](https://zh.wikipedia.org/wiki/%E9%80%9A%E7%94%A8%E4%B8%AD%E9%97%B4%E8%AF%AD%E8%A8%80)
[OCP](https://zh.wikipedia.org/wiki/%E5%BC%80%E9%97%AD%E5%8E%9F%E5%88%99)
<style>
/*--------------- view ---------------*/
body[style],
body[style*="background-color: white;"] {
background-color: #1e1e1e !important;
}
body {
color: #abb2bf;
}
.ui-view-area,
.markdown-body,
.ui-content {
background: #1e1e1e;
color: #abb2bf;
}
h1,
h2,
h3,
h4,
h5,
h6,
p {
color: #ddd;
}
hr {
border-color: #6d6d6d;
}
/* form */
.form-control {
background: #333;
color: #fff;
}
.form-control::placeholder,
.form-control::-webkit-input-placeholder,
.form-control:-moz-placeholder,
.form-control::-moz-placeholder,
.form-control:-ms-input-placeholder {
color: #eee;
}
/*--------------- navbar ---------------*/
.header {
background-color: #0e0e0e;
border-color: #0e0e0e;
}
.navbar {
background-color: #0e0e0e;
border-color: #0e0e0e;
}
.navbar a {
color: #eee !important;
}
.navbar .btn-group label {
background-color: #0e0e0e;
color: #eee;
border-color: #555;
}
.navbar .btn-group label.btn-default:focus,
.navbar .btn-group label.btn-default:hover {
background-color: #2a2a2a;
color: #eee;
border-color: #555;
}
.navbar .btn-group label.active {
background-color: #555;
color: #eee;
border-color: #555;
}
.navbar .btn-group label.active:focus,
.navbar .btn-group label.active:hover {
background-color: #555;
color: #eee;
border-color: #555;
}
.navbar-default .btn-link:focus,
.navbar-default .btn-link:hover {
color: #eee;
}
.navbar-default .navbar-nav>.open>a,
.navbar-default .navbar-nav>.open>a:focus,
.navbar-default .navbar-nav>.open>a:hover {
background-color: #555;
}
.dropdown-header {
color: #aaa;
}
.dropdown-menu {
background-color: #222;
border: 1px solid #555;
border-top: none;
}
.dropdown-menu>li>a {
color: #eee;
}
.dropdown-menu>li>a:focus,
.dropdown-menu>li>a:hover {
background-color: #555555;
color: #eee;
}
.dropdown-menu .divider {
background-color: #555;
}
.header .open .dropdown-menu {
background-color: #202020;
}
.navbar .announcement-popover {
background: #4F4F4F;
}
.navbar .announcement-popover .announcement-popover-header {
background: #2e2e2e;
border-bottom: 1px solid #2e2e2e;
}
.navbar .announcement-popover .announcement-popover-body {
background: #4F4F4F;
color: #eee;
}
.navbar .announcement-popover .announcement-popover-footer {
background: #4F4F4F;
}
.navbar .announcement-area .caption.inverse {
color: #eee;
}
.label-warning {
background-color: #ffc107;
color: #212529;
}
/*--------------- history / recent ---------------*/
.list.row-layout li .item {
border-color: #696c7d;
}
.list.row-layout li:nth-last-of-type(1) .item {
border-bottom: none;
}
.list li .item {
background: #1c1c1c;
}
.list li:hover .item,
.list li:focus .item {
background: #404040;
}
.list li .item h4 {
color: #fff;
}
.list li p {
color: #ccc;
}
.list li p i {
font-style: normal;
}
.list li .item .content .tags span {
background: #555;
}
.list li .item.wide .content .title a,
.list li .item.wide .content .title a:focus,
.list li .item.wide .content .title a:hover {
color: #ddd;
}
.ui-item {
color: #fff;
opacity: 0.7;
}
.ui-item:hover,
.ui-item:focus {
opacity: 1;
color: #fff;
}
.list li .item.wide hr {
border-color: #6d6d6d;
}
.overview-widget-group .btn,
.multi-select-dropdown-menu .ui-dropdown-label,
.multi-select-dropdown-menu .dropdown-options,
.form-control {
border-color: #6d6d6d;
}
.multi-select-dropdown-menu .dropdown-options .ui-option:hover {
background-color: #4d4d4d;
color: #eee;
}
#overview-control-form #overview-keyword-input-container .select2-container {
background-color: #3e4045 !important;
}
#overview-control-form #overview-keyword-input-container .select2-container .select2-choices {
background-color: #3e4045;
}
.search {
background-color: #3e4045;
color: #eee;
}
.btn.btn-gray {
background: #1b1b1b;
}
.btn.btn-gray:hover {
background: #4d4d4d;
color: #eee;
}
.search::placeholder,
.search::-webkit-input-placeholder,
.search:-moz-placeholder,
.search::-moz-placeholder,
.search:-ms-input-placeholder {
color: #eee;
}
.btn.btn-gray {
border-color: #6d6d6d;
background: #333;
color: #eee;
}
.select2-default {
color: #eee !important;
}
.select2-results .select2-highlighted {
background: #4d4d4d;
color: #eee;
}
.select2-container-multi .select2-choices {
background: #3e4045;
}
.select2-container-multi .select2-choices .select2-search-choice {
background: #131313;
color: #eee;
border-color: #555;
box-shadow: none;
}
.btn-default,
.btn-default:focus {
color: #eee;
background-color: #2e2e2e;
border-color: #6a6a6a;
}
.btn-default.active.focus,
.btn-default.active:focus,
.btn-default.active:hover,
.btn-default:active.focus,
.btn-default:active:focus,
.btn-default:active:hover,
.open>.dropdown-toggle.btn-default.focus,
.open>.dropdown-toggle.btn-default:focus,
.open>.dropdown-toggle.btn-default:hover {
background: #737373;
}
.btn-default:hover {
color: #fff;
background-color: #7d7d7d;
border-color: #6a6a6a;
}
.overview-widget-group .btn.active {
background-color: #6a6a6a;
color: #eee;
}
.overview-widget-group .btn:hover {
background-color: #7d7d7d;
color: #eee;
border-color: #636363;
}
.overview-widget-group .slider.round {
border-color: #ccc;
}
.overview-widget-group .slider.round:before {
border-color: #ccc;
}
.overview-widget-group input:checked+.slider {
background-color: #ccc;
}
.ui-category-description-icon a {
color: #eee;
}
.item .ui-history-pin.active {
color: #f00;
}
.ui-history-close {
color: #eee;
opacity: 0.5;
}
.pagination>li>a,
.pagination>li>span {
color: #eee;
background-color: #2e2e2e;
border-color: #6a6a6a;
}
.pagination>li>a:hover {
color: #fff;
background-color: #7d7d7d;
border-color: #6a6a6a;
}
.pagination>.disabled>a,
.pagination>.disabled>a:focus,
.pagination>.disabled>a:hover,
.pagination>.disabled>span,
.pagination>.disabled>span:focus,
.pagination>.disabled>span:hover {
color: #eee;
background-color: #2e2e2e;
border-color: #6a6a6a;
}
.pagination.dark>li>a,
.pagination.dark>li>span {
color: #aaa;
}
/*--------------- settings ---------------*/
.section .form-horizontal .form-group .btn-default {
font-size: 16px;
border-color: #6d6d6d;
background-color: #333;
color: #FFF;
}
.section .form-horizontal .form-group .btn-default:hover,
.section .form-horizontal .form-group .btn-default:focus {
background-color: #737373;
color: #FFF;
}
.section .form-horizontal .form-control:focus {
border-color: #bbb;
}
/*--------------- share view ---------------*/
#notificationLabel,
.ui-infobar .btn.ui-edit {
color: #eee;
border-color: #6a6a6a;
}
.ui-infobar__user-info li {
color: #bbb;
}
footer {
background: #101010;
color: #bbb;
border-top: 1px solid #454545;
}
footer a {
color: #bbb;
}
/*--------------- doc view ---------------*/
.markdown-body h1,
.markdown-body h2,
.markdown-body h3,
.markdown-body h4,
.markdown-body h5,
.markdown-body h6,
.markdown-body hr,
#doc>h1 {
color: #ddd;
border-color: #777 !important;
}
.h1 .small,
.h1 small,
.h2 .small,
.h2 small,
.h3 .small,
.h3 small,
.h4 .small,
.h4 small,
.h5 .small,
.h5 small,
.h6 .small,
.h6 small,
h1 .small,
h1 small,
h2 .small,
h2 small,
h3 .small,
h3 small,
h4 .small,
h4 small,
h5 .small,
h5 small,
h6 .small,
h6 small {
color: #ddd;
}
.markdown-body p {
color: #ddd;
}
.markdown-body a {
color: #7bf;
}
.markdown-body a
{
color: #7bf !important;
}
.markdown-body ul li,
.markdown-body ol li {
color: #ddd;
}
.markdown-body blockquote {
color: #ddd;
border-left-color: #777;
font-size: 16px;
}
.markdown-body code,
code {
color: #dfdfdf !important;
background-color: #424a55;
}
.markdown-body pre {
background-color: #1e1e1e;
border: 1px solid #555 !important;
color: #dfdfdf;
}
blockquote .small,
blockquote footer,
blockquote small {
color: #bbb;
}
.mark,
mark {
background-color: rgba(255, 255, 0, 0.32) !important;
color: #ddd;
margin: .1em;
padding: .1em .2em;
}
/* Todo list */
.task-list-item-checkbox {
margin: 0.18em 0 0.2em -1.3em !important;
}
.task-list-item input[type=checkbox] {
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
position: relative;
top: -1px;
margin: 0 1rem 0 0;
cursor: pointer;
}
.task-list-item input[type=checkbox]::before {
-webkit-transition: all 0.1s ease-in-out;
-moz-transition: all 0.1s ease-in-out;
transition: all 0.1s ease-in-out;
content: "";
position: absolute;
left: 0;
z-index: 1;
width: 16px;
height: 16px;
border: 2px solid #F44336;
}
.task-list-item input[type=checkbox]:checked::before {
-webkit-transform: rotate(-48deg);
-moz-transform: rotate(-48deg);
-ms-transform: rotate(-48deg);
-o-transform: rotate(-48deg);
transform: rotate(-48deg);
height: 9px;
border-color: #00E676;
border-top-style: none;
border-right-style: none;
}
.task-list-item input[type=checkbox]::after {
content: "";
position: absolute;
top: -0.125rem;
left: 0;
width: 16px;
height: 16px;
background: #333;
cursor: pointer;
}
/* table */
.markdown-body table tr {
background-color: #1e1e1e;
border-top: none;
border-bottom: 1px solid rgba(255, 255, 255, 0.3);
}
.markdown-body table tr:first-child {
border-top: 1px solid rgba(255, 255, 255, 0.2);
}
.markdown-body table tr:nth-child(2n) {
background-color: #333;
}
.markdown-body table tr th {
color: #64B5F6;
}
.markdown-body table th,
.markdown-body table td {
border: none;
}
.markdown-body table tr th:first-child,
.markdown-body table tr td:first-child {
border-left: 1px solid rgba(255, 255, 255, 0.1);
}
.markdown-body table tr th:last-child,
.markdown-body table tr td:last-child {
border-right: 1px solid rgba(255, 255, 255, 0.1);
}
.markdown-body table tr td {
color: #ddd;
}
.markdown-body pre.flow-chart,
.markdown-body pre.sequence-diagram,
.markdown-body pre.graphviz,
.markdown-body pre.mermaid,
.markdown-body pre.abc {
background-color: #fff !important;
}
/* alert */
.alert h1,
.alert h2,
.alert h3,
.alert h4,
.alert h5,
.alert h6,
.alert p,
.alert ul li,
.alert ol li {
color: #31708f;
}
.alert a {
color: #002752;
font-weight: 700;
}
.alert h1:first-child,
.alert h2:first-child,
.alert h3:first-child,
.alert h4:first-child,
.alert h5:first-child,
.alert h6:first-child {
margin-top: 0;
}
.markdown-body .alert>p {
margin-top: 0px;
margin-bottom: 10px;
}
.markdown-body .alert>ul,
.markdown-body .alert>ol {
margin-bottom: 16px;
}
.markdown-body .alert>*:last-child {
margin-bottom: 0;
}
.alert-warning {
background-color: #fff3cd;
border-color: #ffeeba;
}
/* scroll bar */
.ui-edit-area .ui-resizable-handle.ui-resizable-e {
background-color: #303030;
border: 1px solid #303030;
box-shadow: none;
}
/* info bar */
.ui-infobar {
color: #999;
}
/* permission */
.permission-popover-btn-group .btn.focus,
.permission-popover-btn-group .btn:active,
.permission-popover-btn-group .btn:focus,
.permission-popover-btn-group .btn.active {
background-color: #6a6a6a !important;
color: #eee !important;
border-color: #555 !important;
}
.permission-popover-btn-group .btn:hover,
.permission-popover-btn-group .btn.active:hover {
background-color: #7d7d7d !important;
color: #eee !important;
border-color: #636363 !important;
}
.ui-delete-note a:hover,
.ui-delete-note a:focus,
.ui-delete-note a:active {
background-color: #dc3545 !important;
}
.ui-invitee-invite {
border-color: #6a6a6a !important;
}
.ui-invitee-invite:hover,
.ui-invitee-invite:focus {
background-color: #737373;
color: #eee !important;
}
.ui-invitee.ui-invitee-list .ui-invitee-remove,
.ui-invitee.ui-invitee-list .ui-invitee-remove:hover,
.ui-invitee.ui-invitee-list .ui-invitee-remove:focus,
.ui-invitee.ui-invitee-list .ui-invitee-remove:active {
background-color: #dc3545;
border: 1px solid #dc3545;
}
.select2-container {
background: #202020;
}
.select2-container-multi .select2-choices .select2-search-field input {
color: #eee;
}
.select2-container-multi .select2-choices .select2-search-field input.select2-active {
color: #000;
}
.select2-drop {
background: #202020;
color: #eee;
}
.select2-results .select2-no-results,
.select2-results .select2-searching,
.select2-results .select2-ajax-error,
.select2-results .select2-selection-limit {
background: #202020;
}
/* table of contents block*/
.ui-toc-dropdown {
width: 42vw;
max-height: 90vh;
overflow: auto;
text-align: inherit;
}
/* table of contents text*/
.ui-toc-dropdown .nav>li>a {
font-size: 14px;
font-weight: bold;
color: #ddd;
}
/* table of contents text: active*/
.ui-toc-dropdown .nav>.active:focus>a,
.ui-toc-dropdown .nav>.active:hover>a,
.ui-toc-dropdown .nav>.active>a {
color: #7bf;
border-left-color: #7bf;
}
/* table of contents text: focus, hover*/
.ui-toc-dropdown .nav>li>a:focus,
.ui-toc-dropdown .nav>li>a:hover {
color: #7bf;
border-left-color: #7bf;
}
/* drop down floating table of contents */
.ui-toc-dropdown.dropdown-menu {
background: #333;
}
.toc-menu a {
color: #ddd;
}
.toc-menu a:focus,
.toc-menu a:hover {
color: #7bf;
}
/*--------------- editor ---------------*/
.cm-m-markdown {
color: #ddd;
}
.cm-s-one-dark .cm-header,
.cm-m-xml.cm-attribute {
color: #ffa653;
}
.cm-s-one-dark .cm-string,
.cm-s-one-dark .cm-variable-2 {
color: #7bf;
}
.cm-m-markdown.cm-variable-3 {
color: #ff7e7e;
}
.cm-s-one-dark .cm-link {
color: #b0ee83;
}
.cm-s-one-dark .CodeMirror-linenumber {
color: #666;
}
.cm-strong {
color: #f4511e;
}
.cm-s-one-dark .cm-comment {
color: #a9a9a9;
}
.cm-matchhighlight {
color: #ffea00;
}
.cm-positive {
color: #11bf64;
}
.cm-negative {
color: #ff3e3e;
}
.dropdown-menu.CodeMirror-other-cursor {
border: 2px solid #4d4d4d;
background-color: #202020;
}
.dropdown-menu.CodeMirror-other-cursor li a {
color: #ececec;
}
/*--------------- book mode ---------------*/
.topbar {
background: #1e1e1e;
}
.btn.focus,
.btn:focus,
.btn:hover {
color: #aaa;
}
.summary {
background: #1e1e1e;
}
.summary,
.toolbar {
background: #1e1e1e !important;
border-color: #4d4d4d !important;
}
.toolbar i {
color: #fff;
}
.summary h1,
.summary h2,
.summary h3 .summary hr {
color: #ddd;
border-color: #777 !important;
}
.summary .nav>li>a {
color: #7bf;
}
.summary .nav-pills>li.active>a,
.summary .nav-pills>li.active>a:focus,
.summary .nav-pills>li.active>a:hover {
color: #ff9100;
}
.ui-summary-search {
font-size: 16px;
border: 1px solid #6D6D6D;
background-color: #333;
color: #FFF;
}
.summary h1,
.summary h2,
.summary h3,
.summary h4,
.summary h5,
.summary h6 {
border-color: #454545;
}
/* fix body background color to dark */
div[class$=container-mask] {
background: #1e1e1e;
z-index: 1;
display: block;
}
/* notification */
.dropdown.ui-notification .ui-notification-label,
.dropdown.ui-invitee .ui-invitee-label {
color: #eee;
border-color: #6a6a6a;
}
.ui-notification .dropdown-menu {
border-top: 1px solid #555;
}
/*--------------- help ---------------*/
.modal-header {
background-color: #2a2a2a;
}
.panel-default {
border-color: #6d6d6d;
}
.panel-default>.panel-heading {
background-color: #2a2a2a;
color: #eee;
border-color: #6d6d6d;
}
.panel-body {
background: #2e2e2e;
}
.panel-body a {
color: #7bf;
}
.table>tbody>tr>td,
.table>tbody>tr>th,
.table>tfoot>tr>td,
.table>tfoot>tr>th,
.table>thead>tr>td,
.table>thead>tr>th {
border-color: #6d6d6d;
}
/*--------------- comment ---------------*/
.ui-comment-container .ui-comment-header {
background-color: #2a2a2a;
color: #eee;
border-color: #6d6d6d;
}
.ui-comment-container {
background-color: #2e2e2e;
border-color: #6d6d6d;
}
.ui-comment-container .ui-comments-container .ui-comment .comment-author {
color: #eee;
}
.ui-comment-container .ui-comments-container .ui-comment .timestamp {
color: #aaa;
}
.ui-comment-container .ui-comments-container .ui-comment .comment-content {
color: #eee;
}
.ui-comment-container .ui-comments-container .ui-comment .comment-menu {
color: #eee;
}
.ui-comment-container .ui-comments-container .ui-comment .comment-menu .comment-dropdown-menu {
background: #222;
color: #eee;
border-color: #555;
}
.ui-comment-container .ui-comments-container .ui-comment .comment-menu .comment-dropdown-menu>div:hover {
background-color: #555555;
color: #eee;
}
.ui-comment-container .ui-comments-container .ui-comment .comment-menu:hover,
.ui-comment-container .ui-comments-container .ui-comment .comment-menu:active,
.ui-comment-container .ui-comments-container .ui-comment .comment-menu.active {
background-color: #737373;
color: #eee;
}
.ui-comment-container .ui-comment-input-container {
background-color: #3c3c3c;
}
.ui-comment-container textarea {
background-color: #3e4045;
color: #eee;
border: 1px solid #6d6d6d;
}
.ui-comment-container textarea::placeholder,
.ui-comment-container textarea::-webkit-input-placeholder,
.ui-comment-container textarea:-moz-placeholder,
.ui-comment-container textarea::-moz-placeholder,
.ui-comment-container textarea:-ms-input-placeholder {
color: #eee;
}
@keyframes highlight {
0% {
background-color: #3c3c3c;
}
30% {
background-color: #3c3c3c;
}
100% {
background-color: transparent;
}
}
/*--------------- template ---------------*/
.template-content .modal-header {
background: #2a2a2a;
}
.template-content .close {
color: #fff;
}
.template-content .modal-title {
color: #eee;
}
.template-content .ui-templates-container {
border-color: #6d6d6d;
}
.ui-templates-container .ui-create-template-btn {
background: #446fab;
color: #fff;
}
.ui-template-list-filter .ui-template-list-filter-label,
.ui-template-list-filter .ui-template-list-filter-label:hover {
color: #eee;
}
.ui-template-list .list-group-item.active {
background: #4d4d4d;
}
.ui-template-list .list-group-item.active:focus {
background: #4d4d4d !important;
}
.list-group-item.active,
.list-group-item.active:focus,
.list-group-item.active:hover {
color: #eee;
}
.ui-template-list .list-group-item .list-group-item-heading {
color: #eee;
}
.ui-template-list .list-group-item.active .list-group-item-heading {
color: #eee;
}
.ui-template-list .list-group-item:hover {
background: #4d4d4d !important;
}
.ui-template-item-menu {
color: #eee !important;
}
.ui-template-list .list-group-item {
color: #fff;
}
.ui-template-list .list-group-item .dropdown-container.open {
background-color: #2a2a2a;
}
.ui-template-list .list-group-item .dropdown-container:hover {
background-color: #2a2a2a !important;
}
.template-menu .more-template {
border-color: #6d6d6d;
}
.template-menu .more-template:hover {
color: #eee;
border-color: #6d6d6d;
}
/*--------------- code mirror ---------------*/
.modal-content {
background: #1f2226;
}
.modal-header {
border-bottom: 1px solid #46484f;
}
.modal-footer {
border-top: 1px solid #46484f;
}
a.list-group-item {
background: #1f2226;
color: #ddd;
border: 1px solid #46484f;
}
a.list-group-item .list-group-item-heading {
color: #ddd;
}
a.list-group-item:focus,
a.list-group-item:hover {
background: #434651;
color: #ddd;
}
button.close {
color: #ddd;
opacity: .5;
}
.close:focus, .close:hover {
color: #fff;
opacity: .8;
}
.CodeMirror {
background: #1f2226;
}
.CodeMirror-gutters {
background: #1f2226;
border-right: 1px solid rgba(204, 217, 255, 0.1);
}
.cm-s-default .cm-comment {
color: #888;
}
.cm-s-default .cm-quote {
color: #ddd;
}
.cm-s-default .cm-header {
color: #ffa653;
}
.cm-s-default .cm-link {
color: #b0ee83;
}
.cm-s-default .cm-string,
.cm-s-default .cm-variable-2 {
color: #7bf;
}
.cm-s-default .cm-def {
color: #c678dd;
}
.cm-s-default .cm-number,
.cm-s-default .cm-attribute,
.cm-s-default .cm-qualifier,
.cm-s-default .cm-plus,
.cm-s-default .cm-atom {
color: #eda35e;
}
.cm-s-default .cm-property,
.cm-s-default .cm-variable,
.cm-s-default .cm-variable-3,
.cm-s-default .cm-operator,
.cm-s-default .cm-bracket {
color: #f76e79;
}
.cm-s-default .cm-keyword,
.cm-s-default .cm-builtin,
.cm-s-default .cm-tag {
color: #98c379;
}
.modal-title {
color: #ccc;
}
.modal-body {
color: #ccc !important;
}
div[contenteditable]:empty:not(:focus):before {
color: #aaa;
}
.CodeMirror pre {
color: #ddd;
}
.CodeMirror pre span[style^="background-color: rgb(221, 251, 230)"] {
background-color: #288c27 !important;
}
.CodeMirror pre span[style^="background-color: rgb(249, 215, 220)"] {
background-color: #a52721 !important;
}
/*------- code highlight: Visual Stutdio Code theme for highlight.js -------*/
.hljs {
background: #1E1E1E;
color: #DCDCDC;
}
.hljs-keyword,
.hljs-literal,
.hljs-symbol,
.hljs-name {
color: #569CD6;
}
.hljs-link {
color: #569CD6;
text-decoration: underline;
}
.hljs-built_in,
.hljs-type {
color: #4EC9B0;
}
.hljs-number,
.hljs-class {
color: #B8D7A3;
}
.hljs-string,
.hljs-meta-string {
color: #D69D85;
}
.hljs-regexp,
.hljs-template-tag {
color: #d16969;
}
.hljs-title {
color: #dcdcaa;
}
.hljs-subst,
.hljs-function,
.hljs-formula {
color: #DCDCDC;
}
.hljs-comment,
.hljs-quote {
color: #57A64A;
}
.hljs-doctag {
color: #608B4E;
}
.hljs-meta,
.hljs-meta-keyword,
.hljs-tag {
color: #9B9B9B;
}
.hljs-variable,
.hljs-template-variable {
color: #BD63C5;
}
.hljs-params,
.hljs-attr,
.hljs-attribute,
.hljs-builtin-name {
color: #9CDCFE;
}
.hljs-section {
color: gold;
}
.hljs-emphasis {
font-style: italic;
}
.hljs-strong {
font-weight: bold;
}
/*
.hljs-code {
font-family:'Monospace';
}
*/
.hljs-bullet,
.hljs-selector-tag,
.hljs-selector-id,
.hljs-selector-class,
.hljs-selector-attr,
.hljs-selector-pseudo {
color: #D7BA7D;
}
.hljs-addition {
background-color: #155a36;
color: #dfdfdf;
display: inline-block;
width: 100%;
}
.hljs-deletion {
background-color: #872e2e;
color: #dfdfdf;
display: inline-block;
width: 100%;
}
/*---------- code highlight: Visual Stutdio Code theme for Prism.js ----------*/
code[class*="language-"],
pre[class*="language-"] {
color: #DCDCDC;
}
:not(pre)>code[class*="language-"],
pre[class*="language-"] {
background: #1E1E1E;
}
.token.comment,
.token.block-comment,
.token.prolog,
.token.cdata {
color: #57A64A;
}
.token.doctype,
.token.punctuation {
color: #9B9B9B;
}
.token.tag,
.token.entity {
color: #569CD6;
}
.token.attr-name,
.token.namespace,
.token.deleted,
.token.property,
.token.builtin {
color: #9CDCFE;
}
.token.function,
.token.function-name {
color: #dcdcaa;
}
.token.boolean,
.token.keyword,
.token.important {
color: #569CD6;
}
.token.number {
color: #B8D7A3;
}
.token.class-name,
.token.constant {
color: #4EC9B0;
}
.token.symbol {
color: #f8c555;
}
.token.rule {
color: #c586c0;
}
.token.selector {
color: #D7BA7D;
}
.token.atrule {
color: #cc99cd;
}
.token.string,
.token.attr-value {
color: #D69D85;
}
.token.char {
color: #7ec699;
}
.token.variable {
color: #BD63C5;
}
.token.regex {
color: #d16969;
}
.token.operator {
color: #DCDCDC;
background: transparent;
}
.token.url {
color: #67cdcc;
}
.token.important,
.token.bold {
font-weight: bold;
}
.token.italic {
font-style: italic;
}
.token.entity {
cursor: help;
}
.token.inserted {
color: green;
}
/*---------- code highlight: dark theme for Gist ----------*/
.gist .gist-file {
border: 1px solid #555;
}
.gist .gist-data {
background-color: #1e1e1e;
border-bottom: 1px solid #555;
}
.gist .gist-meta {
background-color: #424a55;
color: #eee;
}
.gist .gist-meta a {
color: #eee;
}
.gist .highlight {
color: #eee;
background-color: #1e1e1e;
}
.gist .blob-num {
color: #afafaf;
}
.gist .blob-code-inner {
color: #dfdfdf;
}
.pl-mb {
color: #fff !important;
}
.pl-c {
color: #57A64A !important;
}
/* comment */
.pl-ent {
color: #569CD6 !important;
}
/* entity */
.pl-e {
color: #9CDCFE !important;
}
.pl-en {
color: #4EC9B0 !important;
}
/* entity attribute */
.pl-smi {
color: #9CDCFE !important;
}
.pl-k {
color: #569cd6 !important;
}
.pl-c1,
.pl-s .pl-v {
color: #4EC9B0 !important;
}
.pl-pds,
.pl-s,
.pl-s .pl-pse .pl-s1,
.pl-sr,
.pl-sr .pl-cce,
.pl-sr .pl-sra,
.pl-sr .pl-sre,
.pl-s .pl-s1 {
color: #D69D85 !important;
}
.pl-s .pl-s1 .pl-pse {
color: #c5dbff !important;
}
/* strings */
.diff-table .pl-c,
.diff-table .pl-ent,
.diff-table .pl-e,
.diff-table .pl-en,
.diff-table .pl-pds,
.diff-table .pl-s,
.diff-table .pl-s .pl-s1,
.diff-table .pl-s .pl-pse .pl-s1,
.diff-table .pl-sr,
.diff-table .pl-sr .pl-cce,
.diff-table .pl-sr .pl-sra,
.diff-table .pl-sr .pl-sre,
.diff-table .pl-k,
.diff-table .pl-smi,
.diff-table .pl-c1,
.diff-table .pl-v {
color: #eee !important;
}
</style>