首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >Android | dagger细枝篇

Android | dagger细枝篇

作者头像
Holiday
发布于 2020-09-03 08:38:26
发布于 2020-09-03 08:38:26
9170
举报
文章被收录于专栏:哈利迪ei哈利迪ei

嗨,我是哈利迪~《看完不忘系列》之dagger(树干篇)一文对dagger做了初步介绍,下面我们一起来瞅瞅dagger的一些细节。

本文约3.5k字,阅读大约9分钟。 Dagger源码基于最新版本2.28.3

目录:

@Binds和@Provides区别

Binds和Provides都是搭配Module(模块,用于支持模块化)使用的,Binds表示抽象和具体的绑定,作用在抽象方法上,如下,

代码语言:javascript
AI代码解释
复制
@Module
abstract class GasEngineModule {//汽油引擎模块
    @Binds
    abstract IEngine makeGasEngine(GasEngine engine);
    //抽象的IEngine接口作为返回值,具体的GasEngine作为入参,形成绑定关系
    //当有地方依赖了IEngine时,这里可以为他提供GasEngine实例
}

为什么用抽象方法,因为这里我们要做的只是声明绑定关系,dagger根据声明就知道如何提供实例了,dagger不会调用这个方法或为他生成具体实现。

当需要提供的实例不是一个而是一组时,Binds可以和集合注解:@IntoSet、@ElementsIntoSet、@IntoMap一起使用,

代码语言:javascript
AI代码解释
复制
@Module
abstract class GasEngineModule {//汽油引擎模块
    @Binds
    @IntoMap //支持入map
    @StringKey("Gas") //使用IntoMap的话,还需要指定一个key
    abstract IEngine makeGasEngine(GasEngine engine);
}

@Module
abstract class ElectricEngineModule {//电动引擎模块
    @Binds
    @IntoMap //支持入map
    @StringKey("Electric")
    abstract IEngine makeElectricEngine(ElectricEngine engine);
}

key的指定也有多种类型,如@StringKey、@IntKey、@LongKey、@ClassKey等。

而Provides就比较简单了,当我们没法用@Inject来标记实例的创建姿势时,可以用@Provides来提供实例,比如Retrofit是三方库的类我们没法标记其构造方法,则可以用Provides提供,

代码语言:javascript
AI代码解释
复制
@Module
public class NetworkModule {
    @Provides
    public Retrofit provideRetrofit() {
        return new Retrofit.Builder()
            .baseUrl("xxx")
            .build();
    }
}

可见Binds用于声明接口和实例的绑定关系,Provides用于直接提供实例,他们都写在可模块化的Module里。

然后经过Component指定modules,这些声明就能被dagger找到了,

代码语言:javascript
AI代码解释
复制
@Component(modules = {GasEngineModule.class, ElectricEngineModule.class}) //传入
public interface CarGraph {
    //...
}

@Subcomponent

Subcomponent即子组件,可以将父组件的能力继承过来,同时扩展自己的能力。现在已经有了@Component的CarGraph来造车,我们可以建一个@Subcomponent的WheelGraph来造轮胎,(虽是轮胎图纸,但也有造车之心)

代码语言:javascript
AI代码解释
复制
@Subcomponent //子组件,轮胎图纸
public interface WheelGraph {
    Wheel makeWheel(); //造轮胎

    @Subcomponent.Factory //告知CarGraph如何创建WheelGraph
    interface Factory {
        WheelGraph create();
    }
}

下面要告知dagger WheelGraph是CarGraph的子组件,需要提供Module,借助Module将子组件的类WheelGraph传给subcomponents,

代码语言:javascript
AI代码解释
复制
@Module(subcomponents = WheelGraph.class)
public class WheelModule {
}

将Module添加到CarGraph,

代码语言:javascript
AI代码解释
复制
@Component(modules = {WheelModule.class})
public interface CarGraph {
 //...

    //提供接口,让使用者能借助Factory拿到WheelGraph实例
    WheelGraph.Factory wheelGraph();
}

使用,

代码语言:javascript
AI代码解释
复制
//轮胎图纸
WheelGraph wheelGraph = carGraph.wheelGraph().create();
//造轮胎
Wheel wheel = wheelGraph.makeWheel();

然后我们看下子组件是如何使用父组件的能力的,在WheelGraph里添加一个inject,

代码语言:javascript
AI代码解释
复制
@Subcomponent
public interface WheelGraph {
 //...

    //告诉dagger谁要注入
    void inject(DaggerActivity activity);
}

把DaggerActivity里的 carGraph.inject(this) 换成 wheelGraph.inject(this),发现mCar也能正常运行,

代码语言:javascript
AI代码解释
复制
class DaggerActivity extends AppCompatActivity {
    @Inject
    Car mCar;
    void onCreate(Bundle savedInstanceState) {
        CarGraph carGraph = DaggerCarGraph.create();
  //carGraph.inject(this);
        WheelGraph wheelGraph = carGraph.wheelGraph().create();
        wheelGraph.inject(this);
        //正常发动
        mCar.start();
    }
}

可见wheelGraph把carGraph的造车能力也给继承过来了。

我们看到生成的DaggerCarGraph类,里面有个内部类WheelGraphImpl(子组件不会生成单独的DaggerXXX类,而是依附于父组件),

代码语言:javascript
AI代码解释
复制
class WheelGraphImpl implements WheelGraph {
    
    @Override
    public Wheel makeWheel() {
        return new Wheel();
    }

    @Override
    public void inject(DaggerActivity activity) {
        injectDaggerActivity(activity);// ↓
    }

    private DaggerActivity injectDaggerActivity(DaggerActivity instance) {
        //跟父组件的注入逻辑一致,还调用了父组件的造车能力DaggerCarGraph.this.makeCar()
        DaggerActivity_MembersInjector.injectMCar(instance, DaggerCarGraph.this.makeCar());
        return instance;
    }
}

谷歌示例会形象些,ApplicationComponent和LoginComponent就是父与子的关系,LoginComponent自己管理LoginViewModel,但同时又继承了父组件的数据获取能力,

@Scope

Scope即作用域,是一种元注解,即作用于注解的注解。@Singleton可以实现全局单例,当父组件CarGraph标记了@Singleton,子组件WheelGraph就不能使用相同的@Singleton了,我们可以自定义注解。

代码语言:javascript
AI代码解释
复制
@Scope //元注解
@Retention(RetentionPolicy.RUNTIME)
public @interface ActivityScope { //表示我想要一个Activity级别的作用域
}

使用,

代码语言:javascript
AI代码解释
复制
@ActivityScope //使用自定义注解
public class Wheel {
}

@ActivityScope //使用自定义注解
@Subcomponent
public interface WheelGraph {
}

@Qualifier

Qualifier即限定符,也是一种元注解。当有多个相同类型的实例要提供时,比如轮胎有最小和最大尺寸都是相同的int类型,

代码语言:javascript
AI代码解释
复制
public class Wheel {
    int minSize;
    int maxSize;

    @Inject
    public Wheel(int minSize, int maxSize) {
        this.minSize = minSize;
        this.maxSize = maxSize;
    }
}

WheelModule进行提供,

代码语言:javascript
AI代码解释
复制
@Module(subcomponents = WheelGraph.class)
public class WheelModule {
    @Provides
    static int minSize() {
        return 12;
    }

    @Provides
    static int maxSize() {
        return 23;
    }
}

这时dagger就会出错了,他不知道多个int的对应关系,需要自定义注解来指定,

代码语言:javascript
AI代码解释
复制
@Qualifier //元注解
@Retention(RUNTIME)
public @interface MinSize {} //限定符注解

@Qualifier //元注解
@Retention(RUNTIME)
public @interface MaxSize {} //限定符注解

然后在Wheel和WheelModule都加上限定即可

代码语言:javascript
AI代码解释
复制
public class Wheel {
    int minSize;
    int maxSize;

    @Inject
    public Wheel(@MinSize int minSize, @MaxSize int maxSize) {//使用自定义注解
        this.minSize = minSize;
        this.maxSize = maxSize;
    }
}

@Module(subcomponents = WheelGraph.class)
public class WheelModule {
    @Provides
    @MinSize //使用自定义注解
    static int minSize() {
        return 12;
    }

    @Provides
    @MaxSize //使用自定义注解
    static int maxSize() {
        return 23;
    }
}

SPI机制

dagger文档里提到了SPI机制,哈迪蹩脚的英文看得一头雾水,不过最近刚好看到了好友丙的文章Dubbo的SPI机制,做了个简单的理解,SPI(Service Provider Interface,服务提供者接口)简单来说,就是先统一接口,然后按需扩展自己的实现类,到了运行的时候再去查找加载对应的实现类,不过这里的实现类,我们集中放在一个事先约定好的地方。

比如MySQL

约定在 Classpath 下的 META-INF/services/ 目录里创建一个以服务接口命名的文件,然后文件里面记录的是此 jar 包提供的具体实现类的全限定名。 这样当我们引用了某个 jar 包的时候就可以去找这个 jar 包的 META-INF/services/ 目录,再根据接口名找到文件,然后读取文件里面的内容去进行实现类的加载与实例化。 -- 敖丙

声明好了实现类后,运行时就会有java自带的ServiceLoader来解析文件,加载实现类(不过Dubbo为了优化自建了一套)。

再比如我们更为熟悉的gradle-plugin开发,也会约定一个地方来声明实现类,在插件工程的resources/META-INF/gradle-plugins/目录下建一个plugin_name.properties文件,声明类的全名,(参见butterknife)

代码语言:javascript
AI代码解释
复制
implementation-class=butterknife.plugin.ButterKnifePlugin

所以SPI简单理解就是一种可扩展的、提供实现类的约定机制。那么SPI对dagger来说有啥用途呢?

注意:dagger的SPI还是实验性的,随时可变

我们看到dagger的spi包下的一个接口BindingGraphPlugin,

代码语言:javascript
AI代码解释
复制
//我是一个插件接口,可以插在dagger图绑定(创建类连接依赖关系)的过程中
public interface BindingGraphPlugin {
 //为Dagger处理器遇到的每个有效根绑定图调用一次。 可以使用diagnosticReporter报告诊断
    void visitGraph(BindingGraph bindingGraph, DiagnosticReporter diagnosticReporter);

 //使用Filer初始化此插件,该Filer可用于基于绑定图编写Java或其他文件。 
    //在访问任何图形之前,此插件的每个实例将调用一次
    default void initFiler(Filer filer) {}

 //...
    default void initTypes(Types types) {}

 //...
    default void initElements(Elements elements) {}

 //...
    default void initOptions(Map<String, String> options) {}

 //返回此插件用于配置行为的注释处理选项。
    default Set<String> supportedOptions() {
        return Collections.emptySet();
    }

 //插件的唯一名称,将在打印到Messager的诊断程序中使用。 默认情况下,使用插件的标准名称
    default String pluginName() {
        return getClass().getCanonicalName();
    }
}

咦,BindingGraphPlugin是啥玩意?你想想,再好好想想,他是不是长得很像我们开发注解处理器APT时做的一些事情,看下ButterKnifeProcessor,

代码语言:javascript
AI代码解释
复制
@AutoService(Processor.class)
//使用AutoService自动帮我们做SPI声明,
//他会创建META-INF/services/javax.annotation.processing.Processor文件,帮我们写入注解处理器的类全名
public final class ButterKnifeProcessor extends AbstractProcessor {
    public void init(ProcessingEnvironment env) {}
    public Set<String> getSupportedOptions() {}
    public Set<String> getSupportedAnnotationTypes() {}
    public boolean process(Set<? extends TypeElement> elements, RoundEnvironment env) {}
}

怎么样,长得是不是还挺像,那就很好理解了,注解处理器在构建时插入一段逻辑来解析注解生成辅助类,那dagger的BindingGraphPlugin就是在图绑定阶段插一段逻辑来做自定义处理嘛。

dagger内置了一些实现类,如DependencyCycleValidator用来检测是否有循环依赖、FailingPlugin用来生成错误报告、InjectBindingValidator用于验证@Inject标记的构造方法...

如果有特殊需求,就可以自定义插件,插入自己的逻辑,例如实现以下功能:

  • 添加项目特定的错误和警告,例如android.content.Context的绑定必须具有@Qualifier或实现DatabaseRelated的绑定必须是作用域
  • 生成额外的Java源文件
  • 将Dagger模型序列化为资源文件
  • 建立Dagger模型的可视化(可将绑定图(依赖关系)转成json/proto,然后渲染成UI

-- dagger

自定义插件使用@AutoService(BindingGraphPlugin.class)进行SPI声明,例如dagger的一个TestPlugin,

代码语言:javascript
AI代码解释
复制
@AutoService(BindingGraphPlugin.class)
public final class TestPlugin implements BindingGraphPlugin {
    private Filer filer;//文件操作

    @Override
    public void initFiler(Filer filer) {
        this.filer = filer;
    }

    @Override
    public void visitGraph(BindingGraph bindingGraph, DiagnosticReporter diagnosticReporter) {
  //定制逻辑...
    }
}

定义好插件后,dagger就会使用java自带的ServiceLoader进行查找和加载,在SpiModule中,

代码语言:javascript
AI代码解释
复制
@Module
abstract class SpiModule {
    private SpiModule() {}

    @Provides
    @Singleton
    static ImmutableSet<BindingGraphPlugin> externalPlugins(
        @TestingPlugins Optional<ImmutableSet<BindingGraphPlugin>> testingPlugins,
        @ProcessorClassLoader ClassLoader processorClassLoader) {
        return testingPlugins.orElseGet(
            () ->
            ImmutableSet.copyOf(
                //ServiceLoader.load
                ServiceLoader.load(BindingGraphPlugin.class, processorClassLoader)));
    }
}

对ServiceLoader.load实现感兴趣的读者,可以看敖丙的文章Dubbo的SPI机制,实现不是很复杂。

延伸

延伸部分略枯燥,纯属个人装B学习记录用,不感兴趣可跳过~?

偷偷装个B,哈迪在公司其实脚本和后端都写过(当然只是内部的管理平台,不可能是核心业务啦),所以分析技术时已经习惯了各种发散和对比,越发觉得其实很多端的技术很是相通~看过Tangram系列的读者应该也见过TangramService项目,这还是用大学时搭的壳来写的...

@Autowired注入

源码基于spring 4.3.13,spring boot 1.5.9

使用姿势,

代码语言:javascript
AI代码解释
复制
@RestController
public class ActivityController {
    @Autowired //自动注入
    private ActivityService activityService;
}

@Service
public class ActivityService {} //注意:因为代码不多,所以就没按规范抽成接口和Impl

那么activityService实例是如何自动注入的呢?

Spring会扫描@Component注解的Bean,然后AbstractAutowireCapableBeanFactory#populateBean负责注入bean的属性,他里边调了ibp.postProcessPropertyValues,我们看到AutowiredAnnotationBeanPostProcessor#postProcessPropertyValues,

代码语言:javascript
AI代码解释
复制
//AutowiredAnnotationBeanPostProcessor.java
public PropertyValues postProcessPropertyValues() {
    //1.获取Class中关于属性注入相关注解的元数据
    InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
    //2.完成属性注入操作
    metadata.inject(bean, beanName, pvs);
    return pvs;
}

1.findAutowiringMetadata主要是做检查和缓存,他调了buildAutowiringMetadata,跟进,

代码语言:javascript
AI代码解释
复制
//AutowiredAnnotationBeanPostProcessor.java
private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
    LinkedList<InjectionMetadata.InjectedElement> elements = 
        new LinkedList<InjectionMetadata.InjectedElement>();
    //目标类,如我们的ActivityController
    Class<?> targetClass = clazz;
    do {
        //收集
        final LinkedList<InjectionMetadata.InjectedElement> currElements =
            new LinkedList<InjectionMetadata.InjectedElement>();
        //记录有@Autowired,@Value等注解的field
        ReflectionUtils.doWithLocalFields(targetClass, new ReflectionUtils.FieldCallback() {
            @Override
            public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException {
                AnnotationAttributes ann = findAutowiredAnnotation(field);
                if (ann != null) {
                    //...
                    currElements.add(new AutowiredFieldElement(field, required));
                }
            }
        });
        //记录有@Autowired,@Value等注解的method
        ReflectionUtils.doWithLocalMethods(targetClass, new ReflectionUtils.MethodCallback() {
            @Override
            public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException {
                //...
                AnnotationAttributes ann = findAutowiredAnnotation(bridgedMethod);
                if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
                    //...
                    currElements.add(new AutowiredMethodElement(method, required, pd));
                }
            }
        });
        //收集
        elements.addAll(0, currElements);
        //继续往上查找父类
        targetClass = targetClass.getSuperclass();
    }while (targetClass != null && targetClass != Object.class);
    //返回包装好的元数据
    return new InjectionMetadata(clazz, elements);
}

解析类的注解得到包装好的元数据后,就调用2.metadata.inject进行注入,他又调了element.inject,我们直接看到AutowiredFieldElement#inject,

代码语言:javascript
AI代码解释
复制
//AutowiredFieldElement
protected void inject(Object bean, String beanName, PropertyValues pvs) throws Throwable {
    //根据元数据,解析属性值,找到我们的ActivityService实例
    //DefaultListableBeanFactory.resolveDependency -> doResolveDependency -> 
    //findAutowireCandidates -> addCandidateEntry -> candidates.put -> 
    //descriptor.resolveCandidate -> AbstractBeanFactory.getBean -> getObjectForBeanInstance...
    value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
    //设置可访问
    ReflectionUtils.makeAccessible(field);
    //将实例注入
    field.set(bean, value);
}

可见@Autowired的注入是基于反射来做的~

gRPC

RPC(Remote Procedure Call)是远程过程调用,后端进行服务化后,通常会在一个主机上调用另一个主机提供的方法,比如获取一个用户收藏的商品,用户服务器就会调用商品服务器的方法,什么?居然还能调用远程主机应用的方法?其实可以这么理解,就是基于一定协议和数据格式进行通信,比如http+json/proto,但是直接这么用不方便,就封装成接口方法的方式来调用了,看起来是调了一个方法,其实内部进行了远程通信。像Dubbo、Spring Cloud、gRPC就是一些远程过程调用的框架。可以类比Android的跨进程通信IPC,只不过RPC不仅跨了进程,还跨了主机。

gRPC是谷歌开源的高性能远程过程调用框架,dagger文档的gRPC就寥寥几句,还不完善,看不出个所以然,就先不看了,简单了解下就行...

尾声

由于哈迪没有dagger实战经验,写起来还是有点吃力的,写着写着就有种搬文档的感觉...而且dagger的使用程度貌似也不怎么高,真要用得炉火纯青,可能还得要靠深刻理解业务,能够发掘契合度极高的业务高手了吧...怎么说呢,趁年轻好奇心足够强烈,多学点还是好的,我们下期见~?

系列文章:

  • 《看完不忘系列》之dagger
  • 《看完不忘系列》之Retrofit
  • 《看完不忘系列》之okhttp
  • 《看完不忘系列》之Glide

参考资料

  • GitHub & 文档 & API
  • csdn - Dubbo & csdn - Dubbo的SPI机制
  • 简书 - SpringBoot源码解析@Value,@Autowired实现原理

欢迎关注原创技术公众号:哈利迪ei

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-08-30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 哈利迪ei 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
Dynamic Language Runtime 微软打出的王牌
      Dynamic Language Runtime(DLR)。DLR和IronPython全部开源,如果你微软这样的动作吃惊,请看看Microsoft 的 OpenSource Licence,可以到codeplex下载。新的动态语言运行时(Dynamic Language Runtime,DLR)向CLR中加入了一小部分核心特性,使之得到显著改善。它向平台中加入了一系列明确为动态语言需求所设计的服务,包括同享的动态类型系统、标准托管模型(Standard Hosting Model),以及轻松生
张善友
2018/01/30
1.1K0
Miguel de Icaza 细说 Mix 07大会上的Silverlight和DLR
Mono之父Miguel de Icaza 详细报道微软Mix 07大会上的Silverlight和DLR ,上面还谈到了Mono and Silverlight, 实现WPF目前不在Mono团队的近期计划之内,不过Silverlight for linux是不远的将来.就可以用.索性将他转载过来,内容如下: Mix 07, Silverlight, Dynamic Languages Runtime and OpenSource A very impressive set of demos at Mix
张善友
2018/01/31
9740
微软发布IronRuby
微软公司在其MIX07大会上宣布了IronRuby,一个运行在.NET CLR之上的Ruby实现的发布。其中,IronRuby与Java VM上的JRuby类似,但与Ruby/.NET Bridge之类的工具不同,这类工具只是将Ruby解释器于.NET VM相连接。 IronPython是运行在.NET之上的Python实现,其开发人员Jim Hugunin向我们阐述了IronRuby、IronPython和另外一些动态语言之下的技术的更进一步信息: 新的动态语言运行时(Dynamic Language R
张善友
2018/01/30
1K0
微软在动态语言支持上超越了Java?
当.NET在2000/2001年第一次发布的时候,Java社区认为它仅仅是从语言以及标准库上对Java的一个“克隆”。我们把二者的简单实例代码进行比较以后就可以很轻易地得出这样一个感受。不过,微软从它多年的Java经验中获益匪浅,并且成功解决了一些Sun现在才后知后觉的问题。Java社区也有人开始认为,.NET和CLR要比Java发展得更加快速。Neil Bartlett称: 我认为微软在CLR上的创新速度更快是非常明显的。举例来说:LINQ就是一个极其强大的新特性(补充一下,它基于Haskell语言的mo
张善友
2018/01/30
1K0
是开始学习IronPython 的时候了
Dino's Blog 上写一篇文章介绍了IronPython 2.6的Final版本已经发布。IronPython就是优雅的python编程语言和强大的.NET平台的有机结合, IronPython
张善友
2018/01/22
1.6K0
.NET 基金会项目介绍-DLR/IronPython2/IronPython3
DLR/IronPython2/IronPython3 是属于 .Net 基金会的一个项目,本文将简要介绍该项目相关的信息。
newbe36524
2020/03/16
8750
动态语言满足动态数据库开发
     在微软的Web 2.0大会上,官员们开始介绍“Jasper”。在一场名为“用Dynamic ADO.Net快速建立数据驱动网页”的活动中,微软的官员们开始介绍如何同时使用动态语言的概念和ADO.Net来开发“数据驱动网页”,“这即使是对于最复杂的数据库都是可升级的。”      Jasper是微软ADO.Net Entity Framework的一系列扩展。ADO.Net Entity Framework帮助开发者在数据库中建立数据模型。微软希望将整个ADO.Net Entity Framewor
张善友
2018/01/30
1.2K0
Mono SVN最新代码或者Mono 1.2.5 支持IronPython 2.0
IronPython 2.0基于Dynamic Language Runtime(DLR). Mono开发团队迅速完成了对DLR的支持.IronPython 2.0 Aplal一起发布的DLR(Dynamic Language Runtime )都是采用Microsoft Permissive License (Ms-PL)许可发布的 IronPython架构师Jim Hugunin改变了微软和Opensource社区的关系,微软现在够Open,可以看看微软目前的所有OpenSource方面的Licence
张善友
2018/01/30
9320
Microsoft 的 OpenSource Licence
      看到这篇文章 我的ASP.NET AJAX控件——PopupNotificationExtender:实现OWA或Messenger样式的信息提示窗口 采用Ms-PL协议,后面又在问一个问题:是否有必要开放源代码?故学习了一下微软的所有共享源码协议,看来微软最近两年来在OpenSource方面迈的步子还不小啊。开源代码厂商与产品对微软带来莫大挑战,但该公司过去几年来调整作法以便能跟开放源代码产品(如Linux)作更好的相容,同时也采用了开放源代码开发模式,尤其是跟开发者,Mix07上有一个专门S
张善友
2018/01/26
8670
.NET Core跨平台的奥秘[上篇]:历史的枷锁
微软推出的第一个版本的.NET Framework是一个面向Windows桌面和服务器的基础框架,在此之后,为此微软根据设备自身的需求对.NET Framework进行裁剪,不断推出了针对具体设备类型的.NET Framework版本以实现针对移动、平板和嵌入式设备提供支持。除此之外,在Windows平台之外一致游荡着一只特立独行的猴子(Mono)。.NET平台看起来欣欣向荣,而实际上却日薄西山,就在这个时候微软走了一条唯一正确的道路,那就是基于跨平台理念重新设计的.NET Core,以及由此驱动地对整个.
蒋金楠
2018/01/15
1.5K0
.NET Core跨平台的奥秘[上篇]:历史的枷锁
Phalanger---PHP的.NET编译器
除了IronPython,微软正试着让.NET平台支持更多你我熟知的动态语言,例如Perl、PHP、Ruby。根据IronPython的创造者、也是微软CLR开发部门主管Jim Hugunin表示,微软正试着以不同的方式协助动态语言进驻.NET平台,不论是加强.NET底层的支持,或者是以patterns & practices协助开发人员以动态语言构建程序。 听说过Phalanger的人可能不多,但您一定听过PHP,而Phalanger则是PHP的.NET编译器;也就是能将PHP程序代码编译成.NET平台的
张善友
2018/01/29
8730
IronPython 2.0 beta 5
ironpython 2.0 beta 5 已经发布,下载地址:http://www.codeplex.com/IronPython/Release/ProjectReleases.aspx?Rele
张善友
2018/01/31
1.1K0
IronPython 2.0 发布了
       DLR团队终于发布了 IronPython 2.0 ,IronPython 2.0完全基于Dynamic Language Runtime (DLR). DLR允许多个动态语言在系统类型层面实现互操作。这个版本修复大概500多个bug,有453个来自codeplex社区的反馈。热烈祝贺开发团队发布了这一个重大的里程碑版本。可以到codeplex上去下载,下面是一些重要的链接: 项目codeplex站点http://www.codeplex.com/IronPython 下载地址 http:/
张善友
2018/01/30
6770
TestDriven.NET (2.7 Beta) 支持Silverlight/CoreCLR
Silverlight 1.1,在这个微软已经提供下载alpha版本中,包含了一个缩减版的CLR,还有最新发布的Dynamic Language Runtime (DLR)。Silverlight将被插入Internet Explorer、Mozilla和Safari浏览器中,这意味着缩减版的CLR也能够运行在这些平台上。 微软将这个缩减的CLR称为“Core CLR”(核心CLR)(这个核心CLR的代码代号是Tolesto,微软表示这恰巧是一个环绕土星的卫星的名字。)Core CLR将包含garbage
张善友
2018/01/30
5610
使用动态语言来制作silverlight
在silverlight beta 2 中已经支持了动态语言.但是在Visual Studio 和 Experssion Blend中还没有使用动态语言的模版.我们目前只可以手动建立. ok  开始吧
用户1172164
2018/01/16
1K0
使用动态语言来制作silverlight
C# 中的动态类型
.NET 4.0 中引入的 dynamic 关键字为 C# 编程带来了一个范式转变。对于 C# 程序员来说,强类型系统之上的动态行为可能会让人感到不适 —— 当您在编译过程中失去类型安全性时,这似乎是一种倒退。
zls365
2021/04/02
4.4K0
Mono 的Virtual PC 虚拟机
随着Mono 2.4.2的发布,Mono官方增加了一种Virtual PC虚拟机镜像。这对于经常在Windows平台使用Virtual PC的各位同学来说是个好消息,可以很轻松的在linux环境下测试.NET应用程序了。这个VPC的虚拟机环境是openSUSE 11.1 + Mono 2.4.2。可以到这里下载 http://go-mono.com/mono-downloads/ Mono 2.4.2正式加入了对asp.net mvc项目的支持,也就是说asp.net mvc项目现在也可以在Mono上跑了。
张善友
2018/01/29
8790
C#4.0新增功能01 动态绑定 (dynamic 类型)
C# 4 引入了一个新类型 dynamic。 该类型是一种静态类型,但类型为 dynamic 的对象会跳过静态类型检查。 大多数情况下,该对象就像具有类型 object 一样。 在编译时,将假定类型化为 dynamic 的元素支持任何操作。 因此,不必考虑对象是从 COM API、从动态语言(例如 IronPython)、从 HTML 文档对象模型 (DOM)、从反射还是从程序中的其他位置获取自己的值。 但是,如果代码无效,则在运行时会捕获到错误。
张传宁IT讲堂
2019/09/17
2.1K0
C#4.0新增功能01 动态绑定 (dynamic 类型)
IronPython死而复生
IronPython是一个运行在.Net框架通用语言运行库上的实现(Common Language Runtime,CLR)。这个项目曾一度停滞不前,最近,团队换了领导者,带来了新的进展。 Jeff Hardy,IronPython项目的前领导人,这个月在IronPython用户邮件列表中确认了这次调职,称“由于多种原因,我没有足够的时间来带领这个项目了,所以我将这个项目交给Alex Earl和Benedikt Eggers。 Python支持.Net, .Net支持Python IronPython采用C
CSDN技术头条
2018/02/12
1.9K0
利用IronJs在.NET程序里面跑javascript脚本
本文介绍了一种使用Iron.js在.NET程序中运行JavaScript脚本的方法,通过动态语言运行时(DLR)实现。该方法可以方便地为动态语言添加自定义逻辑,提高开发效率。
MJ.Zhou
2018/01/04
1.2K0
利用IronJs在.NET程序里面跑javascript脚本
相关推荐
Dynamic Language Runtime 微软打出的王牌
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
首页
学习
活动
专区
圈层
工具
MCP广场
首页
学习
活动
专区
圈层
工具
MCP广场